2013-11-15 3 views
2

Я запускаю AsyncTask в методе onStart(), потому что я хочу, чтобы он всегда перезагружал данные из базы данных SQLite, когда пользователь возвращается к этому фрагменту. Это потому, что это ListFragment, и щелчок по элементу приводит к появлению другого фрагмента в двухпанельном макете на планшетах или в Activity, который использует ViewPager для всех элементов в списке. В последнем случае мне нужно перезагрузить элементы, потому что пользователь может удалять элементы из ViewPager.API 8 - AsyncTask NullPointerException после 2 вращений

Теперь я тестирую свои макеты на разных устройствах и API.

На Froyo (API 8) NexusOne AVD, если я поворачиваю экран один раз, он снова запускает AsyncTask и повторно отображает данные. Если я сделаю это снова, я получаю исключение NullPointerException. Этого не происходит, когда я запускаю другой AVD, используя API 10+ (я могу повернуть дисплей, который мне нужен). Я даю ему много времени, чтобы завершить первое вращение, прежде чем делать второе.

Здесь LogCat:

11-14 21:03:46.485: E/AndroidRuntime(326): FATAL EXCEPTION: main 
11-14 21:03:46.485: E/AndroidRuntime(326): java.lang.NullPointerException 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.widget.ArrayAdapter.init(ArrayAdapter.java:271) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:150) 
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$MyAdapter.<init>(MyListFragment.java:279) 
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$getMyAsync.onPostExecute(MyListFragment.java:393) 
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$getMyAsync.onPostExecute(MyListFragment.java:1) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask.finish(AsyncTask.java:417) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask.access$300(AsyncTask.java:127) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.Handler.dispatchMessage(Handler.java:99) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.Looper.loop(Looper.java:123) 
11-14 21:03:46.485: E/AndroidRuntime(326): at android.app.ActivityThread.main(ActivityThread.java:4627) 
11-14 21:03:46.485: E/AndroidRuntime(326): at java.lang.reflect.Method.invokeNative(Native Method) 
11-14 21:03:46.485: E/AndroidRuntime(326): at java.lang.reflect.Method.invoke(Method.java:521) 
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
11-14 21:03:46.485: E/AndroidRuntime(326): at dalvik.system.NativeStart.main(Native Method) 

MyListFragment.java:279 является призыв к ArrayAdapter .constructor [EDIT]

super(context, 0, myListArray); 

onPostExecute (MyListFragment.java:393 это :

mAdapter = new MyAdapter(getActivity(), myListArray); 

Вышеупомянутый не получает exe cuted, если myListArray имеет значение null.

Я добавил это выше этой инструкции:

if (getActivity() == null) { 
    Log.d(TAG, "getActivity() is null"); 
} 

getActivity() возвращает нуль на API 8 устройства!

Это просто ошибка с тестовой средой Eclipse/ADT и/или AVD? Или это произойдет на реальных телефонах тоже?

Спасибо.

РЕДАКТИРОВАТЬ

Метод для запуска AsyncTask:

@Override 
public void onStart() { 
    super.onStart(); 
    mProgressBarLayout.setVisibility(View.VISIBLE); 
    new getListAsync().execute(mType); 
} 

AsyncTask (внутренний частный класс ListFragment):

private class getListAsync extends AsyncTask<EFFECT_TYPE, Void, List<Item>> { 

    @Override 
    protected List<Item> doInBackground(EFFECT_TYPE... params) { 
     List<Item> items; 
     items = DatabaseManager.get(getActivity()).getItems(params[0]); 
     return items; 
    } 

    @Override 
    protected void onPostExecute(List<Item> result) { 
     super.onPostExecute(result); 
     mProgressBarLayout.setVisibility(View.GONE); 
     mItemList = result; 
     if (mItemList != null) { 
      if (getActivity() == null) { 
       Log.d(TAG, "getActivity() is null"); <---- THIS GETS LOGGED ON THE 2nd ROTATE! 
      } 
393 -----------> mAdapter = new MyAdapter(getActivity(), mItemList); 
      setListAdapter(mAdapter); 
     } 
    } 

} 

РЕДАКТИРОВАТЬ # 2

Ну, это невозможно.

У меня уже есть onAttach(), так что я сделал это:

Добавить новую переменную MyListFragment:

private Activity mParentActivity = null; 

Modified onAttach():

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    mCallbacks = (Callbacks) activity; 
    mParentActivity = activity; 
    if (mParentActivity == null) { 
     Log.d(TAG, "onAttach() called with null Activity"); 
    } 
} 

onPostExecute:

@Override 
    protected void onPostExecute(List<Item> result) { 
     super.onPostExecute(result); 
     mProgressBarLayout.setVisibility(View.GONE); 
     mItemList = result; 
     if (mItemList != null) { 
      if (mParentActivity == null) { 
       Log.d(TAG, "mParentActivity is null"); 
      } 
      mAdapter = new MyAdapter(mParentActivity, mItemList); 
      setListAdapter(mAdapter); 
     } 
    } 

} 

мП arentActivity здесь NULL! Несмотря на то, что onAttach() успешно выполнен с действительным действием до того, как он получил метод onStart().

AsyncTask разбивается на API 8.

+0

Вы узнали, какая переменная имеет значение null .. в вашем обращении к супер ..? – JoxTraex

+0

Да, контекст. См. Нижнюю часть моего сообщения, пожалуйста. –

+0

Вы должны опубликовать больше кода о том, как/при попытке использовать контекст. – JoxTraex

ответ

0

Вот мое решение сейчас. Если кто-то знает о лучшем, напишите об этом.

@Override 
public void onStart() { 
    super.onStart(); 
    mProgressBarLayout.setVisibility(View.VISIBLE); 
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) { 
     new getItemsAsync().execute(mType); // Do the AsyncTask for API 10+ 
    } else { 
     // For FROYO only, do the operation on the main thread 
     mItemsList = DatabaseManager.get(mParentActivity).getItems(mType); 
     mProgressBarLayout.setVisibility(View.GONE); 
     if (mItemsList != null) { 
      mAdapter = new MyAdapter(mParentActivity, mItemsList); 
      setListAdapter(mAdapter); 
     } 
    } 
} 

Это работает.

Смежные вопросы