有以下片段:package tanat.androidtesttask.fragments;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.google.firebase.crash.FirebaseCrash;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.realm.Realm;
import io.realm.RealmAsyncTask;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;
import tanat.androidtesttask.BuildConfig;
import tanat.androidtesttask.activity.InfoRoutActivity;
import tanat.androidtesttask.R;
import tanat.androidtesttask.activity.MainActivity;
import tanat.androidtesttask.database.DBHelper;
import tanat.androidtesttask.database.RealmController;
import tanat.androidtesttask.model.RealmModel;
import tanat.androidtesttask.service.BroadcastService;
import tanat.androidtesttask.utils.JSONParsing;
import tanat.androidtesttask.utils.LoadLocalData;
import tanat.androidtesttask.errorreporter.Log;
public class ListFragment extends android.app.ListFragment implements SwipeRefreshLayout.OnRefreshListener{
@BindView(R.id.refresh) SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.standart_layout) LinearLayout contentLayout;
@BindView(R.id.error_layout) LinearLayout errorLayout;
@BindView(R.id.errorTextView) TextView errorTextView;
//button to update if an error
@OnClick(R.id.refreshButton)
void onRefreshClick() {
onRefresh();
}
private View rootView;
private final static int STATUS_START = 100;
private final static int STATUS_FINISH = 200;
private final static String PARAM_RESULT = "result";
private final static String PARAM_STATUS = "status";
public final static String BROADCAST_ACTION = "tanat.androidtesttask.activity";
private BroadcastReceiver broadcastReceiver;
private LoadLocalData loadLocalData;
DBHelper dbHelper;
Realm realm;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_item, null);
ButterKnife.bind(this, rootView);
swipeRefreshLayout.setOnRefreshListener(this);
intent = new Intent(getActivity(), BroadcastService.class);
setsConnection();
loadLocalData = new LoadLocalData(getActivity());
dbHelper = new DBHelper(getActivity());
Realm.init(getActivity());
setRetainInstance(true);
return rootView;
}
Intent intent;
private ArrayList data = null;
private void setsConnection (){
broadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(PARAM_STATUS, 0);
if (status == STATUS_START) {
if (BuildConfig.USE_LOG) {Log.d("server start task");}
FirebaseCrash.log("server start task");
}
if (status == STATUS_FINISH) {
if (BuildConfig.USE_LOG) {Log.d("server finish task");}
FirebaseCrash.log("server finish task");
data = intent.getStringArrayListExtra(PARAM_RESULT);
procesShowData();
saveCache();
}
}
};
IntentFilter intFilt = new IntentFilter(BROADCAST_ACTION);
getActivity().registerReceiver(broadcastReceiver, intFilt);
}
@Override
public void onStart() {
super.onStart();
loadData();
procesShowData();
}
@Override
public void onPause(){
// save the data so that you do not load it again when return to the fragment
if(data != null && !data.get(0).toString().equals("false")) {
if (BuildConfig.USE_LOG) {Log.d("pause before save");}
//save data in file
loadLocalData.writeFile(FILE_NAME, new JSONParsing().dispatch());
}
if (BuildConfig.USE_LOG) {Log.d("pause last save");}
super.onPause();
}
@Override
public void onDestroy() {
getActivity().unregisterReceiver(broadcastReceiver);
getActivity().stopService(intent);
super.onDestroy();
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
loadLocalData.writeFile(FILE_NAME, new JSONParsing().dispatch());
Intent intent = new Intent(ListFragment.this.getContext(), InfoRoutActivity.class);
intent.putExtra("position", position);
startActivity(intent);
}
@Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
getActivity().startService(intent);
}
private String FILE_NAME = "JsonTestTask";
// loading data
private void loadData (){
// start show progress dialog
swipeRefreshLayout.setRefreshing(true);
// upload local data
data = loadLocalData.returnArray(FILE_NAME);
//if there is no data, load it from the network
if (data == null || data.size() == 0 || data.get(0).toString().equals("false")) {
data = null;
getActivity().startService(intent);
}
}
private void procesShowData (){
if(data != null){
if(data.get(0).toString().equals("false")){
contentLayout.setVisibility(View.INVISIBLE);
errorLayout.setVisibility(View.VISIBLE);
errorTextView.setText(data.get(1).toString());
} else {
// if network operation true
errorLayout.setVisibility(View.INVISIBLE);
contentLayout.setVisibility(View.VISIBLE);
// create list
createdList();
}
} else {
errorLayout.setVisibility(View.INVISIBLE);
contentLayout.setVisibility(View.VISIBLE);
createdList();
}
if (data != null) {
swipeRefreshLayout.setRefreshing(false);
}
}
private ArrayAdapter<String> adapter;
// create list
public void createdList(){
if (data != null){
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, data);
} else {
adapter = null;
}
setListAdapter(adapter);
}
public void saveCache (){
int checkTypeDatabase = new MainActivity().checkTypeDatabase;
if (checkTypeDatabase == 1) {
// use Realm database
CacheRealm cacheRealm = new CacheRealm();
cacheRealm.execute();
} else if (checkTypeDatabase == 2) {
// use SQLite database
CacheSQLite cacheSQLite = new CacheSQLite();
cacheSQLite.execute();
}
}
private int id = 0;
private int name_from_city = 1;
private int highlight_from_city = 2;
private int id_from_city = 3;
private int name_to_city = 4;
private int highlight_to_city = 5;
private int id_to_city = 6;
private int info = 7;
private int from_date = 8;
private int from_time = 9;
private int from_info = 10;
private int to_date = 11;
private int to_time = 12;
private int to_info = 13;
private int price = 14;
private int bus_id = 15;
private int reservation_count = 16;
// Caching the query in the Realm database
class CacheRealm extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
ArrayList<String[]> arrayList = new JSONParsing().examineJSONObj();
Realm realm = Realm.getDefaultInstance();
try {
realm.beginTransaction();
RealmResults<RealmModel> results = realm.where(RealmModel.class).findAll();
results.deleteAllFromRealm();
for (int i = 0; i < arrayList.size(); i++) {
RealmModel realmObject = realm.createObject(RealmModel.class);
realmObject.setId(Integer.valueOf(arrayList.get(i)[id]));
realmObject.setName_from_city(arrayList.get(i)[name_from_city]);
realmObject.setHighlight_from_city(arrayList.get(i)[highlight_from_city]);
realmObject.setId_from_city(Integer.valueOf(arrayList.get(i)[id_from_city]));
realmObject.setName_to_city(arrayList.get(i)[name_to_city]);
realmObject.setHighlight_to_city(arrayList.get(i)[highlight_to_city]);
realmObject.setId_to_city(Integer.valueOf(arrayList.get(i)[id_to_city]));
realmObject.setInfo(arrayList.get(i)[info]);
realmObject.setFrom_date(arrayList.get(i)[from_date]);
realmObject.setFrom_time(arrayList.get(i)[from_time]);
realmObject.setFrom_info(arrayList.get(i)[from_info]);
realmObject.setTo_date(arrayList.get(i)[to_date]);
realmObject.setTo_time(arrayList.get(i)[to_time]);
realmObject.setTo_info(arrayList.get(i)[to_info]);
realmObject.setPrice(Integer.valueOf(arrayList.get(i)[price]));
realmObject.setBus_id(Integer.valueOf(arrayList.get(i)[bus_id]));
realmObject.setReservation_count(Integer.valueOf(arrayList.get(i)[reservation_count]));
}
realm.commitTransaction();
} finally {
realm.close();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (BuildConfig.USE_LOG) {Log.d("The cache is written to the Realm database");}
super.onPostExecute(result);
}
}
// Caching the query in the SQLite database
class CacheSQLite extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
ArrayList<String[]> arrayList = new JSONParsing().examineJSONObj();
db.delete(dbHelper.TABLE_NAME, null, null);
for (int i = 0; i < arrayList.size(); i++){
values.put(dbHelper.ID, arrayList.get(i)[id]);
values.put(dbHelper.NAME_FROM_CITY, arrayList.get(i)[name_from_city]);
values.put(dbHelper.HIGHLIGHT_FROM_CITY, arrayList.get(i)[highlight_from_city]);
values.put(dbHelper.ID_FROM_CITY, arrayList.get(i)[id_from_city]);
values.put(dbHelper.NAME_TO_CITY, arrayList.get(i)[name_to_city]);
values.put(dbHelper.HIGHLIGHT_TO_CITY, arrayList.get(i)[highlight_to_city]);
values.put(dbHelper.ID_TO_CITY, arrayList.get(i)[id_to_city]);
values.put(dbHelper.INFO, arrayList.get(i)[info]);
values.put(dbHelper.FROM_DATE, arrayList.get(i)[from_date]);
values.put(dbHelper.FROM_TIME, arrayList.get(i)[from_time]);
values.put(DBHelper.FROM_INFO, arrayList.get(i)[from_info]);
values.put(DBHelper.TO_DATE, arrayList.get(i)[to_date]);
values.put(dbHelper.TO_TIME, arrayList.get(i)[to_time]);
values.put(dbHelper.TO_INFO, arrayList.get(i)[to_info]);
values.put(dbHelper.PRICE, arrayList.get(i)[price]);
values.put(dbHelper.BUS_ID, arrayList.get(i)[bus_id]);
values.put(dbHelper.RESERVATION_COUNT, arrayList.get(i)[reservation_count]);
db.insert(dbHelper.TABLE_NAME, null, values);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (BuildConfig.USE_LOG) {Log.d("The cache is written to the SQLite database");}
super.onPostExecute(result);
}
}
}
问题是,如果您在使用其中一个 AsyncTask 之后调用 onPause 方法(即使在最后一个完成之后)。错误文本如下:
02-01 03:52:39.581 1688-1688/tanat.androidtesttask E/UncaughtException: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference
at android.content.ContextWrapper.openFileOutput(ContextWrapper.java:183)
at tanat.androidtesttask.d.b.a(Unknown Source)
at tanat.androidtesttask.fragments.ListFragment.onListItemClick(Unknown Source)
at android.app.ListFragment$2.onItemClick(ListFragment.java:160)
at android.widget.AdapterView.performItemClick(AdapterView.java:310)
at android.widget.AbsListView.performItemClick(AbsListView.java:1145)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3042)
at android.widget.AbsListView.onTouchUp(AbsListView.java:3891)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:3656)
at android.view.View.dispatchTouchEvent(View.java:9294)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
at android.app.Activity.dispatchTouchEvent(Activity.java:2765)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
at android.view.View.dispatchPointerEvent(View.java:9514)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.ne
02-01 03:52:39.586 1688-1688/tanat.androidtesttask E/AndroidRuntime: FATAL EXCEPTION: main
Process: tanat.androidtesttask, PID: 1688
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference
at android.content.ContextWrapper.openFileOutput(ContextWrapper.java:183)
at tanat.androidtesttask.d.b.a(Unknown Source)
at tanat.androidtesttask.fragments.ListFragment.onListItemClick(Unknown Source)
at android.app.ListFragment$2.onItemClick(ListFragment.java:160)
at android.widget.AdapterView.performItemClick(AdapterView.java:310)
at android.widget.AbsListView.performItemClick(AbsListView.java:1145)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3042)
at android.widget.AbsListView.onTouchUp(AbsListView.java:3891)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:3656)
at android.view.View.dispatchTouchEvent(View.java:9294)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2547)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2240)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
at android.app.Activity.dispatchTouchEvent(Activity.java:2765)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
at android.view.View.dispatchPointerEvent(View.java:9514)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
at
android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.
我不明白问题出在哪里,因为没有一个 asyncTasks 使用 onPause 使用的任何东西。请帮助理解。
罪恶的根源在这里:
您不能依赖创建视图时可用的活动始终存在。特别是结合:
onAttach()/onDetach()片段有自己的生命周期(