片段崩溃ViewPager的OnPageChangeListener的onPageSelected方法

我遇到了一个奇怪的事情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);

}

}

}


回答:

最后,我的团队领导的帮助下,我发现了一些碎片不会附着在HomeActivity崩溃时回到HomeActivity。
onPageSelected方法在onCreateView方法之前被调用。
解决方案是在PlusOneFragment的onPageSeleted方法中执行getActivity null检查。

public void onPageSeleted(int position) { 

if (getActivity() == null) {

return;

}

mValueTv.setText("onPageSeleted-Value:" + position + "--" + SystemClock.currentThreadTimeMillis());

}

以上是 片段崩溃ViewPager的OnPageChangeListener的onPageSelected方法 的全部内容, 来源链接: utcz.com/qa/265543.html

回到顶部