定位变化的碎片崩溃

时间:2014-11-11 14:54:03

标签: java android android-fragments

我的应用程序在方向更改时崩溃。当发生这种情况时,我已经注意遵循默认建议,即每个片段都有一个无参数构造函数,并且由于我在MainActivity中实现了Fragments,因此它们被声明为static。然而,我仍然面临同样的例外,好像我没有这样做。

public class MainActivity extends FragmentActivity {

    public static final String      URL = "url";
    public static final String      ID  = "id";

    private SettingsPageAdapter     pageAdapter;
    private ViewPager               pager;
    private FrameLayout             layoutTabBar;

    public static class SettingsPageAdapter extends FragmentPagerAdapter {


        private final List<Fragment>    fragments;

        public SettingsPageAdapter(FragmentManager fm) {
            super(fm);
            fragments = new ArrayList<Fragment>();
        }

        public void addWebViewItem(String url, String id) {
            final Fragment settingsFragment = new SettingsWebView();
            final Bundle bundle = new Bundle();
            bundle.putString(URL, url);
            bundle.putString(ID, id);
            settingsFragment.setArguments(bundle);
            this.fragments.add(settingsFragment);
        }

        public void addItem(Fragment f, String id) {
            final Bundle bundle = new Bundle();
            bundle.putString(ID, id);
            f.setArguments(bundle);
            this.fragments.add(f);
        }

        @Override
        public Fragment getItem(int position) {
            return this.fragments.get(position);
        }

        @Override
        public int getCount() {
            return this.fragments.size();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {

            getSupportFragmentManager().beginTransaction()
                .add(R.id.bar, new BarFragment()).commit();
        }

        pageAdapter = new SettingsPageAdapter(getSupportFragmentManager());

        pageAdapter.addWebViewItem("https://www.google.com", "WebView 1");
        pageAdapter.addWebViewItem("https://m.bbc.co.uk", "WebView 2");
        pageAdapter.addWebViewItem("http://thorbek.net", "WebView 3");
        pageAdapter.addItem(new ContainerFragment(), "container");

        pager = (ViewPager) findViewById(R.id.container);
        pager.setOffscreenPageLimit(pageAdapter.getCount() - 1);
        pager.setAdapter(pageAdapter);

        pager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int arg0) {
                Log.d("PAGER", "onPageSelected");

            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
                Log.d("PAGER", "onPageScrolled");

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
                Log.d("PAGER", "onPageScrollStateChanged");
                final int currentItem = pager.getCurrentItem();
                final BarFragment barFragment = (BarFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.bar);
                barFragment.setCurrentItem(currentItem);

            }
        });

        layoutTabBar = (FrameLayout) findViewById(R.id.bar);
        initAnimation();
    }

    private void initAnimation() {
         ...
    }

    public static class BarFragment extends Fragment {

        private final List<Button>  buttons         = new ArrayList<Button>();
        private int                 currentIndex    = -1;


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            final View rootView = inflater.inflate(R.layout.fragment_buttonbar,
                container, false);

            initButtons(rootView);

            return rootView;
        }

        @SuppressWarnings("deprecation")
        public void setCurrentItem(int index) {

            if (currentIndex != index) {

                resetButtons();
                buttons.get(index).setBackgroundDrawable(
                    buttons.get(index).getContext().getResources()
                            .getDrawable(R.drawable.button_settings_pressed));
                currentIndex = index;
            }
        }

        @SuppressWarnings("deprecation")
        private void initButtons(final View rootView) {

            ...
        }

        @SuppressWarnings("deprecation")
        private void resetButtons() {
            ...
        }
    }

Java.lang.RuntimeException: Unable to start activity      ComponentInfo{com.example.test/com.example.test.MainActivity}:     android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.test.MainActivity$BarFragment: make sure class name exists, is public, and has an empty constructor that is public
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2351)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2403)
at android.app.ActivityThread.access$700(ActivityThread.java:165)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1379)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5391)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.test.MainActivity$BarFragment: make sure class name exists, is public, and has an empty constructor that is public
at android.support.v4.app.Fragment.instantiate(Fragment.java:435)
at android.support.v4.app.FragmentState.instantiate(Fragment.java:101)
at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1823)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:264)
at com.example.test.MainActivity.onCreate(MainActivity.java:79)
at android.app.Activity.performCreate(Activity.java:5122)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1150)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2315)
Caused by: java.lang.IllegalAccessException: access to class not allowed
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1319)
at android.support.v4.app.Fragment.instantiate(Fragment.java:420)

MainActivity.java:79是 super.onCreate(savedInstanceState);

因此它会立即被引入onAreate of MainActivity。

4 个答案:

答案 0 :(得分:2)

异常非常清楚

make sure class name exists, is public, and has an empty constructor that is public

您的BarFragment课程必须是公开的

public static class BarFragment extends Fragment

或者,您可以通过在创建片段时执行以下操作来避免片段重新创建

setRetainInstance(true)

答案 1 :(得分:1)

您的BarFragment看起来不公开。尝试将其更改为

 public static class BarFragment extends Fragment

此外,您不应将自己的空构造函数添加到片段中。默认构造函数将自动设置,并应正确处理恢复状态。如果需要将参数传递给片段,请尝试使用静态newInstance方法并为其分配一个包。

有关进一步说明,请参阅这些文档:

http://developer.android.com/reference/android/app/Fragment.html#Fragment%28%29

基本上删除你添加的构造函数。

祝你好运

答案 2 :(得分:0)

setRetainInstance(true);

我刚刚放了这条线,它解决了我的问题。

我的代码示例:

public  class PlaceholderFragment extends Fragment{
    String str;
    public PlaceholderFragment (String strDesc1){
        this.str=strDesc1;
        setRetainInstance(true);  //Hear put this line
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState){
        View rootView = inflater.inflate(R.layout.quiz_play_descrption_frg_one_, null,false);
        TextView txtdisc=(TextView) rootView.findViewById(R.id.txt_Discription_quizPlayFragment);
        txtdisc.setText(str);

        return rootView;
    }
}

答案 3 :(得分:0)

当方向改变时,活动再次重新创建,你必须使用savedInstanceState维护碎片状态。

if(savedInstanceState == null) 
{
    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
}