2017-08-17 119 views
0

我有一个Activity与02 tabLayout崩溃的旋转与此错误:片段尚未连接尚未

我在第一个选项卡添加First Fragment,每一件事情是蛮好的,因为我在第二个选项卡添加我Second Fragment

Second Fragment作品,但是当我旋转设备它会崩溃,这是我的代码和logcat的..

我试图附加FragmentTwo我在DIFF MainActivity erent方式..可以有人告诉我什么是wroNg & &我如何正确地做到这一点?

感谢advancE。

主要活动:

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

的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) 

回答

0

问题不在于你的应用程序,问题在于波斯nCalendar库,

您在片段级布局充气PersianCalendarView如果你检查自己的实施PersianCalendarView.java,1它们是一个膨胀的布局和他们正试图在FragmentManager其工作添加一个片段在布局精细。 2.但不仅如此,他们正在试图使用getChildFragmentManager()添加ViewPager问题仅在于她。

你可以问为什么?在已经一个FragmentManager加入这个片段时其工作正常,但现在它的崩溃,对于这一点,你可以检查this S0 Answer

是2 FragmnetManger之间的区别对于这个问题,你可以做3两件事, 1.您可以创建票据并等待结果 2.您可以修复该问题 3.不是在布局中添加,而是在Fragment中创建一个ViewGroup,并且在调用onActivtyCreated时,您可以添加该布局运行时。

EDITED

我试过了样品,我试着将它添加在片段的问题,我面对,其实即使我们的片段连接到活动的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); 
    } 
} 

注:

If you take above approach, Please add some logic and make sure it's not adding multiple time when onStart calls in the Fragment.

+0

嗯,感谢您的信息..我得到的印象是,它是更好地尝试03解决方案,你给我;(我有点新的Android),所以你可以解释更多关于这一点?所以我可以解决我的问题 –

+0

@ DRGNme,我更新了我的示例。看看。 –

+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()

布局
+0

与'onCreateView'相似,'Fragment'有'onActivityCreated'方法。你应该重写它。 – Bob

+0

我做过,像这样,但仍然无效:@Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); .. –

+0

你是否从'onCreateView'中删除了所有上面的代码,并将它放在'onActitivtyCreated'中? – Bob

0

只需推动persianCalendarView.update()线内的FragmentTwoonAttach和从onCreate()移除:

@Override 
public void onAttachFragment(Fragment childFragment) { 
    super.onAttachFragment(childFragment); 
    persianCalendarView.update(); 
} 

另外,从persianCalendarView的内部移除update()OnDayClickedListener。我在测试时添加了该行,并忘记将其从示例应用程序中删除。 您不必更新persianCalendarView,除非您在运行时添加事件时需要更改主题或

+0

是啊最后这些变化固定我的'RotationBug',Tnx。 –