Merge branch 'fix-554--content-resolver-reference' into 'master'

Ensure `getContentResolver()` is not requested from `null` object.

Should fix #554, however I couldn't reproduce this. At the very least, I fail to see how it is possible with this new change for a `null` to get passed to `AppProvider.Helper.categories`, whereas it could've before.

In the process, I also made the database query run on the background thread, then update the UI on the UI thread.

See merge request !224
This commit is contained in:
Daniel Martí 2016-03-07 13:52:55 +00:00
commit ea6b0340d9

View File

@ -7,7 +7,10 @@ import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -72,31 +75,34 @@ public class AvailableAppsFragment extends AppListFragment implements
private final ArrayAdapter<String> adapter; private final ArrayAdapter<String> adapter;
CategoryObserver(ArrayAdapter<String> adapter) { CategoryObserver(ArrayAdapter<String> adapter) {
super(null); // Using Looper.getMainLooper() ensures that the onChange method is run on the main thread.
super(new Handler(Looper.getMainLooper()));
this.adapter = adapter; this.adapter = adapter;
} }
@Override @Override
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
// Wanted to just do this update here, but android tells
// me that "Only the original thread that created a view
// hierarchy can touch its views."
final Activity activity = getActivity(); final Activity activity = getActivity();
// this nullguard is temporary, this Fragment really needs to merged into the Activity if (!isAdded() || adapter == null || activity == null) {
if (activity == null) {
return; return;
} }
activity.runOnUiThread(new Runnable() {
// Because onChange is always invoked on the main thread (see constructor), we want to
// run the database query on a background thread. Afterwards, the UI is updated
// on a foreground thread.
new AsyncTask<Void, Void, List<String>>() {
@Override @Override
public void run() { protected List<String> doInBackground(Void... params) {
if (adapter == null) { return AppProvider.Helper.categories(activity);
return;
}
adapter.clear();
categories = AppProvider.Helper.categories(getActivity());
ArrayAdapterCompat.addAll(adapter, translateCategories(categories));
} }
});
@Override
protected void onPostExecute(List<String> loadedCategories) {
adapter.clear();
categories = loadedCategories;
ArrayAdapterCompat.addAll(adapter, translateCategories(loadedCategories));
}
}.execute();
} }
@Override @Override