Use LiveData to update UI and prevent context leak

Julien LepillerWed Jun 10 23:36:19+0200 2020

284c133

Use LiveData to update UI and prevent context leak

app/src/main/java/eu/lepiller/nani/DictionaryActivity.java

44
import android.os.AsyncTask;
55
import android.os.Bundle;
66
import androidx.appcompat.app.AppCompatActivity;
7+
import androidx.lifecycle.LiveData;
8+
import androidx.lifecycle.MutableLiveData;
9+
import androidx.lifecycle.Observer;
710
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
811
912
import android.util.Log;

2831
2932
public class DictionaryActivity extends AppCompatActivity {
3033
    static final int DICO_REQUEST = 1;
31-
    static final String TAG = "DLIST";
34+
    static final String TAG = "DICO_LIST";
3235
    DictionariesAdapter adapter;
3336
    ArrayList<Dictionary> dictionaries;
37+
    private SwipeRefreshLayout refresher;
3438
3539
    @Override
3640
    protected void onCreate(Bundle savedInstanceState) {

3842
        setContentView(R.layout.activity_dictionary);
3943
4044
        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);
4246
4347
        dictionaries = DictionaryFactory.getDictionnaries(getApplicationContext());
4448
        adapter = new DictionariesAdapter(this, dictionaries);

4751
        if(dictionaries.size() == 0) {
4852
            Snackbar.make(findViewById(R.id.dictionary_view), getString(R.string.no_dico_list),
4953
                    Snackbar.LENGTH_LONG).show();
50-
            new DownloadTask(refresher).execute();
54+
            refresh();
5155
        }
5256
5357
        list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {

5862
                startActivityForResult(intent, DICO_REQUEST);
5963
            }
6064
        });
65+
    }
6166
67+
    @Override
68+
    protected void onResume() {
69+
        super.onResume();
70+
        setObserver();
6271
        refresher.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
6372
            @Override
6473
            public void onRefresh() {
65-
                new DownloadTask(refresher).execute();
74+
                refresh();
6675
            }
6776
        });
77+
        updateDataSet();
6878
    }
6979
7080
    @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();
7488
    }
7589
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+
    }
7899
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;
81110
        }
82111
83112
        @Override
84113
        protected Integer doInBackground(String... strings) {
114+
            refreshing.postValue(true);
85115
            try {
86116
                URL url = DictionaryFactory.getListUrl();
87117
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();

119149
        @Override
120150
        protected void onPostExecute(Integer i) {
121151
            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);
128153
        }
129154
    }
130155
131-
    private void updateDataset() {
156+
    private void updateDataSet() {
132157
        DictionaryFactory.updatePackageList();
133158
        dictionaries.clear();
134159
        dictionaries.addAll(DictionaryFactory.getDictionnaries(getApplicationContext()));

139164
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
140165
        super.onActivityResult(requestCode, resultCode, data);
141166
        if (requestCode == DICO_REQUEST) {
142-
            DictionaryFactory.updatePackageList();
143-
            adapter.notifyDataSetChanged();
167+
            updateDataSet();
144168
        }
145169
    }
146170