旋转崩溃时出现此错误:片段尚未附加

时间:2017-08-17 18:38:46

标签: java android fragment persian-calendar

我有Activity 02 tabLayout

我在第一个标签中添加了First Fragment,因为我在第二个标签中添加了Second Fragment,所以每件事情都很好

我的Second Fragment有效但当我旋转设备时它会崩溃,这是我的代码和logCat ..

我试图以不同的方式将<{em>} FragmentTwo附加到我的MainActivity。任何人都可以告诉我什么是wroNg&amp;&amp;我怎么能正确地做到这一点?

先谢谢。

主要活动:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private int[] tabIcons = {
            R.drawable.ic_tab_note,
            R.drawable.ic_tab_calendar
    };

    private static final int TIME_DELAY = 2000;
    private static long back_pressed;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //////// TOOLBAR
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        actionBar.setDisplayHomeAsUpEnabled(true);

        ///////// DRAWER
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navigationView =
                (NavigationView) findViewById(R.id.navigation_view);
        navigationView.setNavigationItemSelectedListener
                (new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        menuItem.setChecked(true);
                        mDrawerLayout.closeDrawers();
                        Toast.makeText(MainActivity.this,
                                menuItem.getTitle(),
                                Toast.LENGTH_LONG).show();
                        return true;
                    }
                });

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tablayout);
        tabLayout.setupWithViewPager(viewPager);
   }


    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new FragmentOne(), "ONE");
        adapter.addFragment(new FragmentTwo(), "TWO");
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

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

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

        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
//            return mFragmentTitleList.get(position);
            return null;
        }
    }

}

FragmentTwo:

import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.interfaces.OnDayClickedListener;
import ir.mirrajabi.persiancalendar.core.interfaces.OnMonthChangedListener;
import ir.mirrajabi.persiancalendar.core.models.CalendarEvent;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;

public class FragmentTwo extends Fragment {
    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

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

        final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
        final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
        final PersianDate today = calendar.getToday();
        calendar.addLocalEvent(new CalendarEvent(
                today, "Custom event", false
        ));
        calendar.addLocalEvent(new CalendarEvent(
                today.clone().rollDay(2, true), "Custom event 2", true
        ));
        calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
            @Override
            public void onChanged(PersianDate date) {
                Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
            }
        });
        persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
            @Override
            public void onClick(PersianDate date) {
                for (CalendarEvent e : calendar.getAllEventsForDay(date))
                    Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();


                calendar.addLocalEvent(new CalendarEvent(
                        today.clone().rollDay(2, false), "Some event that will be added in runtime", false
                ));
                persianCalendarView.update();
            }
        });

        calendar.setHighlightOfficialEvents(false);
        TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
        TextView txtYear = (TextView) view.findViewById(R.id.txt_year);

        String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
                + calendar.getMonthName(today);
        txtDayMonth.setText(dayAndMonth);
        txtYear.setText(calendar.formatNumber(today.getYear()));

        calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
        persianCalendarView.update();


        return view;
    }

}

这是我的activity_main.xml

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <RelativeLayout
        android:id="@+id/base2"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:tabGravity="fill"
            android:theme="@style/ThemeOverlay.AppCompat.Dark"/>

            <RelativeLayout
                android:id="@+id/relativee"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            layout_weight="1"/>
            </RelativeLayout>
        </LinearLayout>
    </RelativeLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>

这里是fragment_two_layout.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimaryDark"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="24dp">

    <ir.mirrajabi.persiancalendar.PersianCalendarView
        android:id="@+id/persian_calendar"
        android:layout_width="match_parent"
        android:layout_height="290sp"
        app:pcv_colorBackground="#292929"
        app:pcv_colorDayName="#bab6b6"
        app:pcv_colorHoliday="#ffd506"
        app:pcv_colorHolidaySelected="#f1f2f3"
        app:pcv_colorNormalDaySelected="#d9d9d9"
        app:pcv_colorNormalDay="#f3f4f5"
        app:pcv_eventUnderlineColor="#02f0f0"
        app:pcv_fontSize="20sp"
        app:pcv_headersFontSize="14sp"/>
        </android.support.v7.widget.CardView>
        </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginBottom="8dp">

        <TextView
            android:id="@+id/txt_day_month"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/colorAccent"
            android:layout_gravity="center_horizontal"
            android:textSize="30sp"/>

        <TextView
            android:id="@+id/txt_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textColor="@color/colorAccent"
            android:textSize="20sp"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal">

        <Button
            android:id="@+id/change_to_ad"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Change to Gregorian Calendar"
            android:textSize="14dp"/>
    </LinearLayout>
</LinearLayout>

logcat的:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.drgnme.listhamrah/com.drgnme.listhamrah.MainActivity}: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095)
at android.app.ActivityThread.access$1000(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.support.v4.app.Fragment.instantiateChildFragmentManager(Fragment.java:2195)
at android.support.v4.app.Fragment.getChildFragmentManager(Fragment.java:745)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.createViewPagers(CalendarFragment.java:55)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.access$000(CalendarFragment.java:27)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment$1.update(CalendarFragment.java:46)
at ir.mirrajabi.persiancalendar.PersianCalendarView.update(PersianCalendarView.java:116)
at com.drgnme.listhamrah.FragmentTwo.onCreateView(FragmentTwo.java:87)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2239)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1332)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1574)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1641)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2959)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:550)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1238)
at android.app.Activity.performStart(Activity.java:6340)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095) 
at android.app.ActivityThread.access$1000(ActivityThread.java:153) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5451) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

3 个答案:

答案 0 :(得分:0)

将以下所有代码移至onActivityCreated()

final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
        final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
        final PersianDate today = calendar.getToday();
        calendar.addLocalEvent(new CalendarEvent(
                today, "Custom event", false
        ));
        calendar.addLocalEvent(new CalendarEvent(
                today.clone().rollDay(2, true), "Custom event 2", true
        ));
        calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
            @Override
            public void onChanged(PersianDate date) {
                Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
            }
        });
        persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
            @Override
            public void onClick(PersianDate date) {
                for (CalendarEvent e : calendar.getAllEventsForDay(date))
                    Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();


                calendar.addLocalEvent(new CalendarEvent(
                        today.clone().rollDay(2, false), "Some event that will be added in runtime", false
                ));
                persianCalendarView.update();
            }
        });

        calendar.setHighlightOfficialEvents(false);
        TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
        TextView txtYear = (TextView) view.findViewById(R.id.txt_year);

        String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
                + calendar.getMonthName(today);
        txtDayMonth.setText(dayAndMonth);
        txtYear.setText(calendar.formatNumber(today.getYear()));

        calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
        persianCalendarView.update();

除了在onCreateView()

中扩充布局之外,最好不要做任何其他工作

答案 1 :(得分:0)

问题不在您的应用中,问题出现在PersianCalendar Lib中,

如果你在PersianCalendarView.java中检查它们的实现,你在Fragment类的布局中膨胀PersianCalendarView,1。它们正在膨胀一个布局,并且他们试图在该FragmentManager中的那个布局中添加一个Fragment并且它正在工作精细。 2.但不仅仅是那个Fragment中他们试图使用getChildFragmentManager()添加ViewPager问题只是她的问题。

你可以问为什么?已经有一个FragmentManager添加了这个Fragment,它的工作正常,但现在它正在崩溃,为此,你可以检查this S0 Answer中的2 FragmnetManger之间的区别

对于这个问题,你可以做三件事, 1.您可以为他们创建票证并等待结果 你可以解决这个问题 3.而不是添加布局,只需在Fragment中创建一个ViewGroup,当调用onActivtyCreated时,您可以添加该布局运行时。

<强> EDITED

我尝试了那个样本,并且我尝试将其添加到Fragment中,我遇到的问题是,实际上即使我们的Fragment附加到Activity上也没有附加CalendarView片段,所以我在解决方案3中提到我们可以添加它在onActivtyCreated中出错了。

然后我们如何暂时解决?

我通过添加onStart中的视图解决了(我知道这是错误的地方,这将在Fragment的生命周期中多次调用),但我们可以添加一些逻辑,我们只能添加此日历视图一旦让它现在工作,直到他们的lib中的开发工具。

我的样本:

我的片段布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="ir.mirrajabi.pc.sample.BlankFragment">

    <LinearLayout
        android:id="@+id/calendar_container"
        android:layout_width="match_parent"
        android:layout_height="290dp"
        android:orientation="vertical"/>

    <TextView
        android:id="@+id/txt_day_month"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textColor="#f0f2f3"
        android:textSize="30sp"/>

    <TextView
        android:id="@+id/txt_year"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textColor="#c6d9e2"
        android:textSize="20sp"/>

</FrameLayout>

片段代码

public class BlankFragment extends Fragment {

    private LinearLayout mLinearLayout;

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

        mLinearLayout= (LinearLayout) view.findViewById(R.id.calendar_container);

        return view;
    }

    @Override
    public void onStart() {
        super.onStart();

        final PersianCalendarView persianCalendarView = new PersianCalendarView(getContext());

        // All your remaining PersianCalendarView implementation code here
        mLinearLayout.addView(persianCalendarView);
    }
}

注意:

  

如果你采取上述方法,请添加一些逻辑并确保它   在片段中的onStart调用时不添加多个时间。

答案 2 :(得分:0)

只需在persianCalendarView.update()的{​​{1}}内移动FragmentTwo行,然后将其从onAttach移除:

onCreate()

同时从@Override public void onAttachFragment(Fragment childFragment) { super.onAttachFragment(childFragment); persianCalendarView.update(); } 的{​​{1}}内删除update()。我在测试时添加了该行,忘记将其从示例应用中删除。 您不必更新persianCalendarView ,除非您需要更改主题在运行时添加事件