带有 ViewPager 的 FragmentActivity:方向更改时崩溃 [英] FragmentActivity with ViewPager: Crash on orientation change

查看:17
本文介绍了带有 ViewPager 的 FragmentActivity:方向更改时崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 FragmentActivity 中使用了 ViewPager.方向改变时我会崩溃.

I have used ViewPager in FragmentActivity. I am getting a crash when orientation changes.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    context = this;
    loadInitialData();
    setActionBar();
    initializeUiComponents();
}

private void initializeUiComponents() {
    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    }

我的数据是动态地从数据库中来的,我必须调用 Sysnctask,它在 onResume() 中从数据库中获取数据.这是 Asynctask 的 onPostExecute().

My data is coming dynamically from the database, and I have to call the Sysnctask which is getting the datat from database in onResume(). Here is onPostExecute() of the Asynctask.

protected void onPostExecute(Void result) {
        
            mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
            mViewPager.setAdapter(mSectionsPagerAdapter);
        }
        mSectionsPagerAdapter.notifyDataSetChanged();
        }
}

添加 FragmentAdapterCode:

Adding FragmentAdapterCode:

public class SectionsPagerAdapter extends FragmentPagerAdapter {
    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }
    
    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = new PayeeListSectionFragment();
        Bundle args = new Bundle();
        args.putInt(PayeeListSectionFragment.ARG_SECTION_NUMBER, position + 1);
        fragment.setArguments(args);
        return fragment;
    }
    
    @Override
    public int getCount() {
        return 2;
    }
    
    @Override
    public CharSequence getPageTitle(int position) {
        
        return string;
    }
}

添加片段代码:

public class PayeeListSectionFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this fragment.
     */
    public static final String ARG_SECTION_NUMBER = "section_number";
    
    public PayeeListSectionFragment() {
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = null;
        \ rootView inflated
        return rootView;
    }
}

使用的xml是:

 <android.support.v4.view.ViewPager
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PayeeListActivity" >

    <!--
This title strip will display the currently visible page title, as well as the page
titles for adjacent pages.

    -->

    <android.support.v4.view.PagerTitleStrip
        android:id="@+id/pager_title_strip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:background="#33b5e5"
        android:paddingBottom="4dp"
        android:paddingTop="4dp"
        android:textColor="#fff" />
</android.support.v4.view.ViewPager>

我在改变方向时遇到以下崩溃:

I am getting the following crash on orientation change:

06-07 11:01:57.834: E/AndroidRuntime(766): FATAL EXCEPTION: main  
06-07 11:01:57.834: E/AndroidRuntime(766): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.walletv2.activity/com.walletv2.activity.PayeeListActivity}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment: make sure class name exists, is public, and has an empty constructor that is public  
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3692)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.access$700(ActivityThread.java:141)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1240)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.os.Looper.loop(Looper.java:137)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.main(ActivityThread.java:5041)
06-07 11:01:57.834: E/AndroidRuntime(766):  at java.lang.reflect.Method.invokeNative(Native Method)
06-07 11:01:57.834: E/AndroidRuntime(766):  at java.lang.reflect.Method.invoke(Method.java:511)
06-07 11:01:57.834: E/AndroidRuntime(766):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
06-07 11:01:57.834: E/AndroidRuntime(766):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
06-07 11:01:57.834: E/AndroidRuntime(766):  at dalvik.system.NativeStart.main(Native Method)
06-07 11:01:57.834: E/AndroidRuntime(766): Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment: make sure class name exists, is public, and has an empty constructor that is public
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.support.v4.app.Fragment.instantiate(Fragment.java:405)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.support.v4.app.FragmentState.instantiate(Fragment.java:97)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1767)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:208)
06-07 11:01:57.834: E/AndroidRuntime(766):  at com.walletv2.activity.PayeeListActivity.onCreate(PayeeListActivity.java:78)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.Activity.performCreate(Activity.java:5104)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
06-07 11:01:57.834: E/AndroidRuntime(766):  ... 12 more
06-07 11:01:57.834: E/AndroidRuntime(766): Caused by: java.lang.InstantiationException: can't instantiate class com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment; no empty constructor
06-07 11:01:57.834: E/AndroidRuntime(766):  at java.lang.Class.newInstanceImpl(Native Method)
06-07 11:01:57.834: E/AndroidRuntime(766):  at java.lang.Class.newInstance(Class.java:1319)
06-07 11:01:57.834: E/AndroidRuntime(766):  at android.support.v4.app.Fragment.instantiate(Fragment.java:394)
06-07 11:01:57.834: E/AndroidRuntime(766):  ... 19 more

推荐答案

下面几行有几个提示:

原因:android.support.v4.app.Fragment$InstantiationException:无法实例化片段 com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment:确保类名存在,是公共的,并且有一个空的构造函数公开

Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment: make sure class name exists, is public, and has an empty constructor that is public

还有:

06-07 11:01:57.834: E/AndroidRuntime(766): Caused by: java.lang.InstantiationException: can't instantiate class com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment;没有空的构造函数

06-07 11:01:57.834: E/AndroidRuntime(766): Caused by: java.lang.InstantiationException: can't instantiate class com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment; no empty constructor

这表明您已向 PayeeListSectionFragment 内部类添加了参数化构造函数.不幸的是,这行不通,因为 Android 依赖于使用反射调用非参数化构造函数来恢复片段在配置更改时的状态(除其他外).

That suggests that you've added a parameterized constructor to your PayeeListSectionFragment inner class. Unfortunately, that won't work, as Android relies on invoking a non-parameterized constructor using reflection in order to restore a fragment's state on configuration changes (amongst other things).

如果您想为片段提供一个或多个参数,则必须将它们插入 Bundle 并将其设置为参数,使用 setArguments(Bundle).看看 DetailsFragmentCountingFragment 中的文档 以获取有关如何执行此操作的示例.

If you want to supply one or more parameters to a fragment, you'll have to plug them into a Bundle and set it as argument, using setArguments(Bundle). Have a look at the DetailsFragment and CountingFragment in the documentation for an example on how to do that.

这个问题也可能出现在另一种情况下,这对于那些不太熟悉 Java 的人来说可能不太明显.如果你的片段是一个嵌套类,比如一些 Activity,请确保你声明了内部类 static.例如,在上述问题的上下文中,它应该是一个 public static class PayeeListSectionFragment(强调 static 修饰符).这样内部类就不会保留对外部类的引用,并且可以拥有自己的生命周期,而不依赖于外部类.如果没有 static 修饰符,则嵌套类不能在不实例化外部类的情况下进行实例化,这意味着 Android 在尝试重新实例化您的片段类时会遇到问题.

This problem can also arise in another situation, which may be less obvious for those not too familiar with Java. If your fragment is a nested class of say some Activity, make sure you declare the inner class static. For example, in the context of above question, it should be a public static class PayeeListSectionFragment (with an emphasis on the static modifier). That way the inner class won't keep a reference to the outer class and can have its own life cycle, without any dependencies on the outer class. Without the static modifier, the nested class can't be instantiated without instantiating the outer class, which means Android will run into issues when attempting to reinstantiate your fragment class.

另一种解决方案是将内部类移动到它自己的 .java 文件中.这样,所有外部类依赖项都会自动删除.

An alternative solution would be to move the inner class to its own .java file. That way any outer class dependencies are automatically removed.

这篇关于带有 ViewPager 的 FragmentActivity:方向更改时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆