<lambda>null1 package leakcanary.internal.activity.screen
2 
3 import android.app.ActivityManager
4 import android.app.AlertDialog
5 import android.view.View
6 import android.view.ViewGroup
7 import android.widget.ListView
8 import android.widget.TextView
9 import com.squareup.leakcanary.core.R
10 import leakcanary.LeakCanary
11 import leakcanary.internal.activity.LeakActivity
12 import leakcanary.internal.activity.db.HeapAnalysisTable
13 import leakcanary.internal.activity.db.HeapAnalysisTable.Projection
14 import leakcanary.internal.activity.db.executeOnDb
15 import leakcanary.internal.activity.ui.SimpleListAdapter
16 import leakcanary.internal.activity.ui.TimeFormatter
17 import leakcanary.internal.navigation.NavigatingActivity
18 import leakcanary.internal.navigation.Screen
19 import leakcanary.internal.navigation.activity
20 import leakcanary.internal.navigation.goTo
21 import leakcanary.internal.navigation.inflate
22 import leakcanary.internal.navigation.onCreateOptionsMenu
23 import leakcanary.internal.navigation.onScreenExiting
24 
25 internal class HeapDumpsScreen : Screen() {
26   override fun createView(container: ViewGroup) =
27     container.inflate(R.layout.leak_canary_heap_dumps_screen).apply {
28 
29       val unsubscribeRefresh = HeapAnalysisTable.onUpdate {
30         activity<NavigatingActivity>().refreshCurrentScreen()
31       }
32 
33       onScreenExiting { unsubscribeRefresh() }
34 
35       onCreateOptionsMenu { menu ->
36         if (!ActivityManager.isUserAMonkey()) {
37           menu.add(R.string.leak_canary_delete_all)
38             .setOnMenuItemClickListener {
39               AlertDialog.Builder(context)
40                 .setIcon(android.R.drawable.ic_dialog_alert)
41                 .setTitle(R.string.leak_canary_delete_all)
42                 .setMessage(R.string.leak_canary_delete_all_leaks_title)
43                 .setPositiveButton(android.R.string.ok) { _, _ ->
44                   executeOnDb {
45                     HeapAnalysisTable.deleteAll(db)
46                     updateUi {
47                       val listView = findViewById<ListView>(R.id.leak_canary_list)
48                       listView.adapter =
49                         SimpleListAdapter(
50                           R.layout.leak_canary_simple_row, emptyList<Any>()
51                         ) { _, _ -> }
52                     }
53                   }
54                 }
55                 .setNegativeButton(android.R.string.cancel, null)
56                 .show()
57               true
58             }
59         }
60       }
61 
62       findViewById<View>(R.id.leak_canary_import_heap_dump).setOnClickListener {
63         activity<LeakActivity>().requestImportHprof()
64       }
65 
66       findViewById<View>(R.id.leak_canary_dump_heap_now).setOnClickListener {
67         LeakCanary.dumpHeap()
68       }
69 
70       executeOnDb {
71         val projections = HeapAnalysisTable.retrieveAll(db)
72         updateUi { onAnalysesRetrieved(projections) }
73       }
74 
75     }
76 
77   private fun View.onAnalysesRetrieved(projections: List<Projection>) {
78     activity.title = resources.getQuantityString(
79       R.plurals.leak_canary_heap_analysis_list_screen_title,
80       projections.size, projections.size
81     )
82 
83     val listView = findViewById<ListView>(R.id.leak_canary_list)
84 
85     listView.setOnItemClickListener { _, _, position, _ ->
86       val projection = projections[position]
87       val analysisScreen = if (projection.exceptionSummary != null) {
88         HeapAnalysisFailureScreen(projection.id)
89       } else {
90         HeapDumpScreen(projection.id)
91       }
92       goTo(analysisScreen)
93     }
94 
95     listView.adapter =
96       SimpleListAdapter(R.layout.leak_canary_leak_row, projections) { view, position ->
97         val goneView = view.findViewById<TextView>(R.id.leak_canary_count_text)
98         goneView.visibility = View.GONE
99         val timeView = view.findViewById<TextView>(R.id.leak_canary_leak_text)
100         val countView = view.findViewById<TextView>(R.id.leak_canary_time_text)
101 
102         val projection = getItem(position)
103         // Enable means "new"
104         countView.isEnabled = false
105 
106         timeView.text = TimeFormatter.formatTimestamp(view.context, projection.createdAtTimeMillis)
107 
108         val count = projection.exceptionSummary ?: resources.getQuantityString(
109           R.plurals.leak_canary_distinct_leaks,
110           projection.leakCount, projection.leakCount
111         )
112         countView.text = count
113       }
114   }
115 }
116