片段在ViewPager的OnPageChangeListener的onPageSelected方法

时间:2015-05-06 13:56:29

标签: android android-fragments android-viewpager

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

  1. HomeActivity是主页面,其中有一个viewpager。 viewpager中有五个片段(Class PlusOneFragment)。 在fagment中,有两个textview。在onCreateView方法中,我们将一个TextView分配给mValueTv字段。
  2. AboutActivity是用于触发应用程序崩溃的另一个页面。因为我使用了UncaughtExceptionHandler来捕获异常 在自定义Application类中,它继承自 android.app.Application 。那么应用程序将转到HomeActivity。
  3. 但是当崩溃时,那么事情很糟糕。应用程序再次崩溃 这真让我烦恼 在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);
        }
    }
    

    }

1 个答案:

答案 0 :(得分:0)

最后,在我的团队负责人的帮助下,我发现当HomeActivity崩溃回HomeActivity时,一些片段没有附加到HomeActivity上。
在onCreateView方法之前调用onPageSelected方法 解决方案是在PlusOneFragment的onPageSeleted方法中进行getActivity null检查。

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