2015-05-06 56 views
0

我遇到了一個奇怪的事情ViewPager。我Google搜索,但沒有發現任何有用的東西。
所以我發佈我在這裏遇到的,也許以後有人得到同樣的問題,或者幸運的是一些天才傢伙可以解決它。
情況顯示如下:
演示應用程序中有兩個頁面。片段崩潰ViewPager的OnPageChangeListener的onPageSelected方法

  1. HomeActivity是主頁面,它有一個viewpager。 viewpager中有五個片段(Class PlusOneFragment)。 在文章中,有兩個文字瀏覽。在onCreateView方法中,我們將一個TextView分配給mValueTv字段。
  2. AboutActivity是用於觸發應用程序崩潰的其他頁面。因爲我已經使用UncaughtExceptionHandler在自定義應用程序類中捕獲異常 ,該應用程序類從android.app.Application繼承。那麼應用程序將轉到HomeActivity。

但是,當崩潰,然後有些糟透了。應用程序再次崩潰。
這真的搞砸了我。
在HomeActivity中,viewpager有一個ViewPager.OnPageChangeListener。
當頁面發生變化時,將在onPageSelected方法中調用特定位置片段的方法。
該方法將設置片段mValueTv的值。在正常情況下,它可以正常工作,但是當發生崩潰時,該方法會拋出java.lang.NullPointerException異常。

05-06 21:37:24.392 17120-17120/com.rxread.viewpagerissue E/MessageQueue-JNI﹕ java.lang.NullPointerException 
     at com.rxread.viewpagerissue.PlusOneFragment.onPageSeleted(PlusOneFragment.java:49) 
     at com.rxread.viewpagerissue.HomeActivity$1.onPageSelected(HomeActivity.java:33) 
     at android.support.v4.view.ViewPager.scrollToItem(ViewPager.java:571) 
     at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:555) 
     at android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2022) 
     at android.view.View.dispatchTouchEvent(View.java:7725) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2212) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2218) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959) 
     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2242) 
     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1536) 
     at android.app.Activity.dispatchTouchEvent(Activity.java:2458) 
     at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59) 
     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2190) 
     at android.view.View.dispatchPointerEvent(View.java:7905) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4009) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3888) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3499) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468) 
     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3575) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476) 
     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3632) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3499) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449) 
     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5657) 
     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5637) 
     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5608) 
     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5815) 
     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 
     at android.os.MessageQueue.nativePollOnce(Native Method) 
     at android.os.MessageQueue.next(MessageQueue.java:138) 
     at android.os.Looper.loop(Looper.java:123) 
     at android.app.ActivityThread.main(ActivityThread.java:5081) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:515) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
     at dalvik.system.NativeStart.main(Native Method) 

因爲代碼太多,所以我打包了它們。 The demo link is
我真的希望有人能幫助我。 非常感謝。


HomeActivity

public class HomeActivity extends ActionBarActivity { 
ViewPager mViewpager; 
BaseTabHostPagerAdapter mAdapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_home); 

    mViewpager= (ViewPager) this.findViewById(R.id.home_ivp); 
    mViewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){ 

     @Override 
     public void onPageScrolled(int i, float v, int i1) { 

     } 

     @Override 
     public void onPageSelected(int i) { 
      Object object=mAdapter.getItem(i); 
      if(object instanceof PlusOneFragment){ 
       ((PlusOneFragment)object).onPageSeleted(i); 
      } 
     } 

     @Override 
     public void onPageScrollStateChanged(int i) { 

     } 
    }); 

    mAdapter=new BaseTabHostPagerAdapter(getSupportFragmentManager()); 
    mViewpager.setAdapter(mAdapter); 
    mAdapter.addPager("new 1", PlusOneFragment.newInstance("new 1")); 
    mAdapter.addPager("new 2",PlusOneFragment.newInstance("new 2")); 
    mAdapter.addPager("new 3",PlusOneFragment.newInstance("new 3")); 
    mAdapter.addPager("new 4", PlusOneFragment.newInstance("new 4")); 
    mAdapter.addPager("new 5", PlusOneFragment.newInstance("new 5")); 
    mAdapter.notifyDataSetChanged(); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_home, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     AboutActivity.actionTo(this); 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

}


AboutActivity

public class AboutActivity extends ActionBarActivity { 

public static void actionTo(Context context){ 
    Intent intent=new Intent(context,AboutActivity.class); 
    context.startActivity(intent); 
} 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_about); 

    TextView mClickToCrash= (TextView) findViewById(R.id.about_to_crash_tv); 
    mClickToCrash.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      int exception=2-2; 
      int a=3/exception; 
      Toast.makeText(AboutActivity.this, "GO EXCEPTION" + a, Toast.LENGTH_SHORT).show(); 
     } 
    }); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.menu_about, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

PlusOneFragment

public class PlusOneFragment extends Fragment { 
private static final String ARG_PARAM1 = "param1"; 

private String mParam1; 
private TextView mValueTv; 

/** 
* Use this factory method to create a new instance of 
* this fragment using the provided parameters. 
* 
* @return A new instance of fragment PlusOneFragment. 
*/ 
// TODO: Rename and change types and number of parameters 
public static PlusOneFragment newInstance(String name) { 
    PlusOneFragment fragment = new PlusOneFragment(); 
    Bundle args = new Bundle(); 
    args.putString(ARG_PARAM1, name); 
    fragment.setArguments(args); 
    return fragment; 
} 

public PlusOneFragment() { 
    // Required empty public constructor 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (getArguments() != null) { 
     mParam1 = getArguments().getString(ARG_PARAM1); 
    } 
} 

public void onPageSeleted(int position){ 
    mValueTv.setText("onPageSeleted-Value:" +position+"--"+ SystemClock.currentThreadTimeMillis()); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    View view = inflater.inflate(R.layout.fragment_plus_one, container, false); 
    TextView textView= (TextView) view.findViewById(R.id.fragment_name); 
    textView.setText(mParam1); 
    mValueTv= (TextView) view.findViewById(R.id.fragment_value); 
    textView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      mValueTv.setText("Value:"+ SystemClock.currentThreadTimeMillis()); 
      Toast.makeText(v.getContext(),"Toast",Toast.LENGTH_SHORT).show(); 
     } 
    }); 
    return view; 
} 

@Override 
public void onResume() { 
    super.onResume(); 
} 

ViewPagerIssueApplication

public class ViewPagerIssueApplication extends Application{ 
@Override 
public void onCreate() { 
    super.onCreate(); 
    CrashHandler handler = CrashHandler.getInstance(); 
    handler.init(getApplicationContext()); 
    Thread.setDefaultUncaughtExceptionHandler(handler); 
} 

}


CrashHandler

public class CrashHandler implements UncaughtExceptionHandler { 
private static CrashHandler myCrashHandler; 
private Context mContext; 

private CrashHandler() { 

} 

public static synchronized CrashHandler getInstance() { 
    if (myCrashHandler != null) { 
     return myCrashHandler; 
    } else { 
     myCrashHandler = new CrashHandler(); 
     return myCrashHandler; 
    } 
} 

public void init(Context context) { 
    mContext = context; 
} 

@Override 
public void uncaughtException(Thread arg0, Throwable exception) { 
    StringWriter stackTrace = new StringWriter(); 
    exception.printStackTrace(new PrintWriter(stackTrace)); 
    System.err.println(stackTrace); 
    System.exit(1); 
} 

}


BaseTabHostPagerAdapter

public class BaseTabHostPagerAdapter extends FragmentPagerAdapter { 

private List<String> names = new ArrayList<String>(); 
private List<Fragment> fragments = new ArrayList<Fragment>(); 

public BaseTabHostPagerAdapter(FragmentManager fm) { 
    super(fm); 
} 

@Override 
public Fragment getItem(int position) { 

    if(position > fragments.size()){ 
     return null; 
    } 
    return fragments.get(position); 
} 

public List<Fragment> getFragmentsList(){ 
    return fragments; 
} 

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

@Override 
public CharSequence getPageTitle(int position) { 

    if(position > names.size()){ 
     return null; 
    } 
    return names.get(position); 
} 

public void addPager(String tabStr,Fragment fragment) { 

    if (fragment != null) { 
     fragments.add(fragment); 
     names.add(tabStr); 
    } 
} 

public void setTab(int location, String tab){ 

    if(location<0||location>names.size()){ 
     return; 
    } 
    if(null!=tab){ 
     names.remove(location); 
     names.add(location, tab); 
    } 
} 

}


回答

0

最後,我的團隊領導的幫助下,我發現了一些碎片不會附着在HomeActivity崩潰時回到HomeActivity。
onPageSelected方法在onCreateView方法之前被調用。
解決方案是在PlusOneFragment的onPageSeleted方法中執行getActivity null檢查。

public void onPageSeleted(int position) { 
    if (getActivity() == null) { 
     return; 
    } 
    mValueTv.setText("onPageSeleted-Value:" + position + "--" + SystemClock.currentThreadTimeMillis()); 
}