簡體   English   中英

帶有 ViewPager 的 FragmentActivity:方向改變時崩潰

[英]FragmentActivity with ViewPager: Crash on orientation change

我在 FragmentActivity 中使用了 ViewPager。 當方向改變時我會崩潰。

@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()。

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

添加 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>

我在方向更改時遇到以下崩潰:

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:確保類名存在,是公共的,並且有一個公共的空構造函數

和:

06-07 11:01:57.834:E/AndroidRuntime(766):由:java.lang.InstantiationException:無法實例化類 com.walletv2.activity.PayeeListActivity$PayeeListSectionFragment; 沒有空的構造函數

這表明您已向PayeeListSectionFragment內部類添加了參數化構造函數。 不幸的是,這行不通,因為 Android 依賴於使用反射調用非參數化構造函數,以便在配置更改(除其他外)時恢復片段的狀態。

如果您想為片段提供一個或多個參數,則必須將它們插入Bundle並將其設置為參數,使用setArguments(Bundle) 查看文檔中的DetailsFragmentCountingFragment獲取有關如何執行此操作的示例。


這個問題也可能出現在另一種情況下,對於那些不太熟悉 Java 的人來說可能不太明顯。 如果您的片段是一個嵌套類,比如一些Activity ,請確保您聲明內部類static 例如,在上述問題的上下文中,它應該是一個public static class PayeeListSectionFragment (強調static修飾符)。 這樣內部類就不會保留對外部類的引用,並且可以擁有自己的生命周期,而不依賴於外部類。 如果沒有 static 修飾符,嵌套類不能在不實例化外部類的情況下實例化,這意味着 Android 在嘗試重新實例化片段類時會遇到問題。

另一種解決方案是將內部類移動到它自己的.java文件中。 這樣,任何外部類依賴項都會自動刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM