Use LiveData to update UI and prevent context leak
app/src/main/java/eu/lepiller/nani/DictionaryActivity.java
4 | 4 | import android.os.AsyncTask; | |
5 | 5 | import android.os.Bundle; | |
6 | 6 | import androidx.appcompat.app.AppCompatActivity; | |
7 | + | import androidx.lifecycle.LiveData; | |
8 | + | import androidx.lifecycle.MutableLiveData; | |
9 | + | import androidx.lifecycle.Observer; | |
7 | 10 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | |
8 | 11 | ||
9 | 12 | import android.util.Log; | |
… | |||
28 | 31 | ||
29 | 32 | public class DictionaryActivity extends AppCompatActivity { | |
30 | 33 | static final int DICO_REQUEST = 1; | |
31 | - | static final String TAG = "DLIST"; | |
34 | + | static final String TAG = "DICO_LIST"; | |
32 | 35 | DictionariesAdapter adapter; | |
33 | 36 | ArrayList<Dictionary> dictionaries; | |
37 | + | private SwipeRefreshLayout refresher; | |
34 | 38 | ||
35 | 39 | @Override | |
36 | 40 | protected void onCreate(Bundle savedInstanceState) { | |
… | |||
38 | 42 | setContentView(R.layout.activity_dictionary); | |
39 | 43 | ||
40 | 44 | final ListView list_view = findViewById(R.id.dictionary_view); | |
41 | - | final SwipeRefreshLayout refresher = findViewById(R.id.dictionary_refresh_layout); | |
45 | + | refresher = findViewById(R.id.dictionary_refresh_layout); | |
42 | 46 | ||
43 | 47 | dictionaries = DictionaryFactory.getDictionnaries(getApplicationContext()); | |
44 | 48 | adapter = new DictionariesAdapter(this, dictionaries); | |
… | |||
47 | 51 | if(dictionaries.size() == 0) { | |
48 | 52 | Snackbar.make(findViewById(R.id.dictionary_view), getString(R.string.no_dico_list), | |
49 | 53 | Snackbar.LENGTH_LONG).show(); | |
50 | - | new DownloadTask(refresher).execute(); | |
54 | + | refresh(); | |
51 | 55 | } | |
52 | 56 | ||
53 | 57 | list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() { | |
… | |||
58 | 62 | startActivityForResult(intent, DICO_REQUEST); | |
59 | 63 | } | |
60 | 64 | }); | |
65 | + | } | |
61 | 66 | ||
67 | + | @Override | |
68 | + | protected void onResume() { | |
69 | + | super.onResume(); | |
70 | + | setObserver(); | |
62 | 71 | refresher.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | |
63 | 72 | @Override | |
64 | 73 | public void onRefresh() { | |
65 | - | new DownloadTask(refresher).execute(); | |
74 | + | refresh(); | |
66 | 75 | } | |
67 | 76 | }); | |
77 | + | updateDataSet(); | |
68 | 78 | } | |
69 | 79 | ||
70 | 80 | @Override | |
71 | - | protected void onResume() { | |
72 | - | super.onResume(); | |
73 | - | updateDataset(); | |
81 | + | protected void onPause() { | |
82 | + | unsetObserver(); | |
83 | + | super.onPause(); | |
84 | + | } | |
85 | + | ||
86 | + | private void refresh() { | |
87 | + | new DownloadTask().execute(); | |
74 | 88 | } | |
75 | 89 | ||
76 | - | private class DownloadTask extends AsyncTask<String, Integer, Integer> { | |
77 | - | private SwipeRefreshLayout refresher; | |
90 | + | private void setObserver() { | |
91 | + | LiveData<Boolean> data = DownloadTask.getRefreshingData(); | |
92 | + | data.observe(this, new Observer<Boolean>() { | |
93 | + | @Override | |
94 | + | public void onChanged(Boolean refreshing) { | |
95 | + | refresher.setRefreshing(refreshing); | |
96 | + | } | |
97 | + | }); | |
98 | + | } | |
78 | 99 | ||
79 | - | DownloadTask(SwipeRefreshLayout r) { | |
80 | - | refresher = r; | |
100 | + | private void unsetObserver() { | |
101 | + | LiveData<Boolean> data = DownloadTask.getRefreshingData(); | |
102 | + | data.removeObservers(this); | |
103 | + | } | |
104 | + | ||
105 | + | private static class DownloadTask extends AsyncTask<String, Integer, Integer> { | |
106 | + | final private static MutableLiveData<Boolean> refreshing = new MutableLiveData<>(); | |
107 | + | ||
108 | + | static LiveData<Boolean> getRefreshingData() { | |
109 | + | return refreshing; | |
81 | 110 | } | |
82 | 111 | ||
83 | 112 | @Override | |
84 | 113 | protected Integer doInBackground(String... strings) { | |
114 | + | refreshing.postValue(true); | |
85 | 115 | try { | |
86 | 116 | URL url = DictionaryFactory.getListUrl(); | |
87 | 117 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); | |
… | |||
119 | 149 | @Override | |
120 | 150 | protected void onPostExecute(Integer i) { | |
121 | 151 | super.onPostExecute(i); | |
122 | - | refresher.setRefreshing(false); | |
123 | - | updateDataset(); | |
124 | - | if(i == null) | |
125 | - | return; | |
126 | - | Snackbar.make(findViewById(R.id.dictionary_view), getString(i), | |
127 | - | Snackbar.LENGTH_LONG).show(); | |
152 | + | refreshing.setValue(false); | |
128 | 153 | } | |
129 | 154 | } | |
130 | 155 | ||
131 | - | private void updateDataset() { | |
156 | + | private void updateDataSet() { | |
132 | 157 | DictionaryFactory.updatePackageList(); | |
133 | 158 | dictionaries.clear(); | |
134 | 159 | dictionaries.addAll(DictionaryFactory.getDictionnaries(getApplicationContext())); | |
… | |||
139 | 164 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
140 | 165 | super.onActivityResult(requestCode, resultCode, data); | |
141 | 166 | if (requestCode == DICO_REQUEST) { | |
142 | - | DictionaryFactory.updatePackageList(); | |
143 | - | adapter.notifyDataSetChanged(); | |
167 | + | updateDataSet(); | |
144 | 168 | } | |
145 | 169 | } | |
146 | 170 |