1

我的應用程序包含兩個片段的MainActivity中的ViewPager。第一個片段包含ListView。我從來沒有看到這一點,但我看到谷歌約RuntimeException的用戶的報告播放:帶片段的空指針異常

java.lang.RuntimeException: Unable to resume activity {com.my.project/com.my.project.MainActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.my.project/com.my.project.MainActivity}: java.lang.NullPointerException 
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120) 
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668) 
at android.app.ActivityThread.access$1500(ActivityThread.java:117) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:130) 
at android.app.ActivityThread.main(ActivityThread.java:3683) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:507) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:875) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:633) 
at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.my.project/com.my.project.MainActivity}: java.lang.NullPointerException 
at android.app.ActivityThread.deliverResults(ActivityThread.java:2532) 
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2107) 
... 12 more 
Caused by: java.lang.NullPointerException 
at com.my.project.FirstFragment.load(FirstFragment.java:551) 
at com.my.project.MainActivity.onActivityResult(MainActivity.java:132) 
at android.app.Activity.dispatchActivityResult(Activity.java:3908) 
at android.app.ActivityThread.deliverResults(ActivityThread.java:2528) 
... 13 more 

這裏是代碼FirstFragment.java:

public class FirstFragment extends Fragment { 

    ArrayList<ListItemObject> listItems = null; 
    ArrayAdapter<ListItemObject> mAdapter; 

    void load() { 
      mAdapter.clear(); // I get error here, that is FirstFragment.java:551 
      ... 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     super.onCreateView(inflater, container, savedInstanceState); 

     listItems = new ArrayList<ListItemObject>(); 
     mAdapter = new MyAdapter(getActivity(), listItems); 
     listView.setAdapter(mAdapter); 
    } 

} 

也就是說mAdapter的所有occuerences。我不明白,它是如何導致NullPointerException。我認爲有時Fragment1銷燬和重新創建,但沒有onCreateView()。 我與其中一位遇到此問題的用戶交談,他說我錯過了在設置中的「開發人員選項」中取消選中「不要保留活動」後,此錯誤消失。我不知道,我可以修復它嗎?或者我需要說我的所有用戶「取消選中此選項」?

在我NainActivity:

public class MainActivity extends FragmentActivity { 

    Vector<Fragment> fragments; 
    ViewPager viewPager; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     viewPager = (ViewPager) findViewById(R.id.pager); 

     fragments = new Vector<Fragment>(); 
     fragments.add(Fragment.instantiate(this, Fragment1.class.getName())); 
     fragments.add(Fragment.instantiate(this, Fragment2.class.getName())); 

     viewPager.setOffscreenPageLimit(fragments.size()); 
     PagerAdapter pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments); 

     viewPager.setAdapter(pagerAdapter); 

     viewPager.setCurrentItem(0); 
    } 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if(requestCode==1) { 
      ((MainChat)fragments.get(0)).load(); 
     } 
    } 

    class PagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter { 

     private List<Fragment> fragments; 

     public PagerAdapter(FragmentManager fm, List<Fragment> fragments) { 
      super(fm); 
      this.fragments = fragments; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      return this.fragments.get(position); 
     } 

     @Override 
     public int getCount() { 
      return this.fragments.size(); 
     } 

    } 

} 
+2

你確定這是你的'MainActivity'嗎?錯誤清楚地指出'MainActivity :: onActivityResult'上有什麼事情發生,你顯然沒有... –

+0

load()被調用時?可能mAdapter不能通過配置更改持久保存。 –

+0

你當然不需要讓用戶改變他們的設備選項,你必須**修復**這個問題......這可能是_Support Package_中已知問題的結果,但沒有我們只能猜測的更多信息。 –

回答

0

我認爲錯誤的原因是您的MainActivity被摧毀,然後通過Android操作系統正在重建。

這意味着片段列表將再次在MainActivity.onCreate創建()方法,但PagerAdapter不會用那些片段,而是將使用由FragmentManager恢復對您的片段實例(例如PagerAdapter.getItem()將不會被調用)。並且由於您的片段列表中的FirstFragment實例未使用,因此它不會接收對FirstFragment.onCreateView()的調用,並且mAdapter實例將爲stil爲null,那麼您將調用FirstFragment.load()方法。

來解決這個問題,最簡單的(但不是很好)的方法是通過傳遞null作爲savedInstanceState PARAM在MainActivity.onCreate()來抑制你的片段恢復:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(null); 
    ... 
} 

另一種方式去是根據需要創建您的PagerAdapter片段:

@Override 
public Fragment getItem(int position) { 
    switch (position) { 
     case 0: return Fragment.instantiate(this, Fragment1.class.getName()); 
     case 1: return Fragment.instantiate(this, Fragment2.class.getName()); 
     default: throw new RuntimException(); 
    } 
} 

和存儲片段的情況下,這種方式:

@Override 
public Object instantiateItem(View container, int position) { 
    Fragment fr = (Fragment) super.instantiateItem(container, position); 
    fragments[position] = fr; 
    return fr; 
} 

(注意:第二種方式未經我測試,所以它可能不起作用)

順便說一句,你可以選擇Android 4.0設置中的「不要保留活動」開發者選項來測試這些問題。

0

正在發生的事情是,含有該片段的活性已被處置。這可能會在活動未顯示的任何時候發生 - 您的用戶所做的是更改開發人員設置,它會積極摧毀活動,以便您看到類似這樣的編碼問題。問題仍然可能發生,並且設備可用的資源越少(或者因爲內存很少,或者因爲其他許多事情正在運行),Android越經常這樣做。

已經解釋的背景,潛在的問題,讓我們討論的具體問題,您onActivityResult()代碼。該方法在視圖生命週期中的某個點上被調用,然後重新構造碎片和活動的上下文,因此無法在此方法中對碎片進行任何有意義的工作,並確保它始終有效。相反,將響應保存在類級變量中,並在onResume()中使用它,將調用該活動是否已銷燬。另外,您應該將onActivityResult()方法移入片段中 - 並始終在您自己的代碼之前調用super.onActivityResult()

最後要注意的是,Android根據自己的想法破壞並重新創建碎片(例如,當您旋轉設備時,所有碎片都被破壞並重新創建)。因此,您應該確保您瞭解並使用活動和片段生命週期,而不是像Alex的解決方案所暗示的那樣對付他們。這隻會導致其他難以診斷的問題。