繁体   English   中英

ViewPager的OnPageChangeListener的onPageSelected方法上的片段崩溃

[英]Fragment Crashes on ViewPager's OnPageChangeListener's onPageSelected method

我在ViewPager上遇到了一件奇怪的事情。 我用谷歌搜索,但找不到任何有用的东西。
因此,我在这里发布了我遇到的问题,也许以后有人遇到同样的问题,或者幸运的是,有些天才的家伙可以解决它。
情况如下:
演示应用程序中有两个页面。

  1. 主页活动是主页,并且其中有一个viewpager。 viewpager中有五个片段(Class PlusOneFragment)。 在fag中,有两个textview。 在onCreateView方法中,我们将一个TextView分配给mValueTv字段。
  2. AboutActivity是用于触发应用程序崩溃的另一个页面。 因为我已经使用UncaughtExceptionHandler在自定义Application类中捕获异常,该类继承自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)

因为代码太多,所以我打包了它们。 演示链接为
我真的希望有人能帮助我。 非常感谢。


家庭活动

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);
}

}


关于活动

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);
}

加一个片段

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);
}

}


崩溃处理程序

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。
在onCreateView方法之前调用onPageSelected方法。
解决方案是在PlusOneFragment的onPageSeleted方法中执行getActivity null检查。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM