2017-08-17 62 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。 –