2013-01-24 93 views
1

我計劃的信使應用程序,其中包括幾個方面:Android的碎片生命週期

  • 登錄/註冊
  • 聯繫人列表
  • 對話
  • 在線狀態選擇(在線,離開,免打擾, ...)
  • 設置

在智能手機上,應該有一次只能有一個活動,但平板電腦應該有一個帶快捷方式的邊欄(在會話視圖中顯示聯繫人列表,顯示設置類別列表的設置中)。

就我的理解而言,這些區域將是碎片,它們會被插入到一個或多個活動中。

於是我開始創建具有以下佈局的活動(RES/main.xml中):

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <fragment 
     android:id="@id/main_fragment_focus" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

</LinearLayout> 

和相應的平板電腦佈局:(佈局大的土地/ main.xml中)

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal" > 

     <fragment 
      android:id="@id/main_fragment_sidebar" 
      android:layout_width="@dimen/main_sidebar_width" 
      android:layout_height="match_parent" /> 

      <fragment 
     android:id="@id/main_fragment_content" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

</LinearLayout> 

到目前爲止,這麼好。至少就我的想法而言。 所以我創建了一個簡單的活動;我使用ActionBarSherlock,因爲我要爲用戶提供API級別5+兼容性:

package com.pm.messenger; 

import android.os.Bundle; 
import android.support.v4.app.FragmentManager; 
import android.util.Log; 

import com.actionbarsherlock.app.SherlockFragmentActivity; 

public class PMMessengerActivity extends SherlockFragmentActivity { 

    // ------------------------------------------------------------------------- 

    FragmentManager fragmentManager = null; 

    // ------------------------------------------------------------------------- 

    public void onCreate(Bundle savedInstanceState) { 

     // --------------------------------------------------------------------- 

     super.onCreate(savedInstanceState); 

     // --------------------------------------------------------------------- 

     fragmentManager = getSupportFragmentManager(); 

     // --------------------------------------------------------------------- 

     if (savedInstanceState == null) { 

      // ----------------------------------------------------------------- 



      // ----------------------------------------------------------------- 

     } 
     else { 

      // ----------------------------------------------------------------- 



      // ----------------------------------------------------------------- 

     } 

     // --------------------------------------------------------------------- 

     Log.d(getClass().getSimpleName(), "no problem before setContentView"); 

     setContentView(R.layout.main); 

     Log.d(getClass().getSimpleName(), "no problem after setContentView"); 

     // --------------------------------------------------------------------- 

    } 

    // ------------------------------------------------------------------------- 

} 

執行此之後,我的應用程序立即崩潰。首先我想,發生這種情況是因爲我沒有提供任何FragmentManager-FragmentTransactions,但後來我注意到(在插入Log.d-Lines之後)在調用SetContentView時發生崩潰。

logcat的產出:

01-24 16:58:26.728: I/ActivityManager(667): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.pm.messenger/.pmMessengerActivity bnds=[912,542][1008,638]} from pid 877 
01-24 16:58:26.748: D/dalvikvm(26431): Late-enabling CheckJNI 
01-24 16:58:26.758: I/ActivityManager(667): Start proc com.pm.messenger for activity com.pm.messenger/.pmMessengerActivity: pid=26431 uid=10009 gids={3003, 1015} 
01-24 16:58:26.778: E/jdwp(26431): Failed sending reply to debugger: Broken pipe 
01-24 16:58:26.778: D/dalvikvm(26431): Debugger has detached; object registry had 1 entries 
01-24 16:58:26.788: D/OpenGLRenderer(877): Flushing caches (mode 1) 
01-24 16:58:26.828: D/pmMessengerActivity(26431): no problem before setContentView 
01-24 16:58:26.858: D/AndroidRuntime(26431): Shutting down VM 
01-24 16:58:26.858: W/dalvikvm(26431): threadid=1: thread exiting with uncaught exception (group=0x40a3e1f8) 
01-24 16:58:26.868: D/OpenGLRenderer(877): Flushing caches (mode 0) 
01-24 16:58:26.868: E/AndroidRuntime(26431): FATAL EXCEPTION: main 
01-24 16:58:26.868: E/AndroidRuntime(26431): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pm.messenger/com.pm.messenger.pmMessengerActivity}: android.view.InflateException: Binary XML file line #7: Error  inflating class fragment 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.access$600(ActivityThread.java:123) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.os.Handler.dispatchMessage(Handler.java:99) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.os.Looper.loop(Looper.java:137) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.main(ActivityThread.java:4424) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.reflect.Method.invokeNative(Native Method) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.reflect.Method.invoke(Method.java:511) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at dalvik.system.NativeStart.main(Native Method) 
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class fragment 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:251) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.actionbarsherlock.internal.ActionBarSherlockNative.setContentView(ActionBarSherlockNative.java:119) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:262) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at com.pm.messenger.pmMessengerActivity.onCreate(pmMessengerActivity.java:48) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.Activity.performCreate(Activity.java:4465) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920) 
01-24 16:58:26.868: E/AndroidRuntime(26431): ... 11 more 
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: java.lang.NullPointerException: name == null 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.VMClassLoader.findLoadedClass(Native Method) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:354) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.loadClass(ClassLoader.java:491) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at java.lang.ClassLoader.loadClass(ClassLoader.java:461) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.Fragment.instantiate(Fragment.java:381) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.Fragment.instantiate(Fragment.java:359) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:262) 
01-24 16:58:26.868: E/AndroidRuntime(26431): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:669) 
01-24 16:58:26.868: E/AndroidRuntime(26431): ... 22 more 
01-24 16:58:26.868: W/ActivityManager(667): Force finishing activity com.pm.messenger/.pmMessengerActivity 
01-24 16:58:27.408: W/ActivityManager(667): Activity pause timeout for ActivityRecord{410d8c98 com.pm.messenger/.pmMessengerActivity} 

現在我認爲,這是崩潰,因爲我沒有在XML提供任何片段類靜態,我不想用這個,我想以動態的方式實現這一點。

當我必須在XML中靜態提供類時,我認爲我還需要多個Activitiys(如LoginActivity,SignupActivity,ContactListActivity,ConversationActivity),但......停止,這可能是不對的,因爲那樣我的碎片就會鬆動他們有權享有imho。

就我的理解而言,片段是我應用程序的一個獨立部分,它實現了像當天活動一樣的功能區域;這些將被嵌入到一個容器活動中,該活動管理着後臺堆棧。

那麼,我的邏輯錯在哪裏? 我應該用FrameView而不是Fragments來使用佈局嗎?不知道。

另外,我沒有找到任何好的,可以理解的,有充分文件記錄的動態片段管理資源。

+0

使用''而不是''佈局 – Selvin

回答

1

您的具體錯誤是由於您試圖誇大不存在的片段,顯然。對於動態片段,您應該將FrameLayout放置在靜態佈局中,並在運行時將片段放入這些幀中。下面是一個佈局示例:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

<View 
    android:id="@+id/anchor" 
    android:layout_width="0dp" 
    android:layout_height="0dp" 
    android:layout_centerInParent="true" /> 

<FrameLayout 
    android:id="@+id/top_left" 
    android:layout_width="0dp" 
    android:layout_height="0dp" 
    android:layout_above="@+id/anchor" 
    android:layout_alignParentLeft="true" 
    android:layout_alignParentTop="true" 
    android:layout_toLeftOf="@+id/anchor"> 

</FrameLayout> 

<FrameLayout 
    android:id="@+id/top_right" 
    android:layout_width="0dp" 
    android:layout_height="0dp" 
    android:layout_above="@+id/anchor" 
    android:layout_alignParentRight="true" 
    android:layout_alignParentTop="true" 
    android:layout_toRightOf="@+id/anchor"> 

</FrameLayout> 

<FrameLayout 
    android:id="@+id/bottom_left" 
    android:layout_width="0dp" 
    android:layout_height="0dp" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentLeft="true" 
    android:layout_below="@+id/anchor" 
    android:layout_toLeftOf="@+id/anchor"> 

</FrameLayout> 

<FrameLayout 
    android:id="@+id/bottom_right" 
    android:layout_width="0dp" 
    android:layout_height="0dp" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentRight="true" 
    android:layout_below="@+id/anchor" 
    android:layout_toRightOf="@+id/anchor"> 

</FrameLayout> 

</RelativeLayout> 

這發生在網格中放置四個大小相同的FrameLayouts。您可以在運行時添加的片段與此:

Fragment levelsF = Fragment.instantiate(this, 
LevelsFragment.class.getName()); 
    Fragment waveF = Fragment.instantiate(this, 
WaveFragment.class.getName()); 
    Fragment lightF = Fragment.instantiate(this,  
LightPlayerFragment.class.getName()); 
    Fragment keyboardF = Fragment.instantiate(this, 
KBFragment.class.getName()); 

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
    ft.add(R.id.top_left, levelsF); 
    ft.add(R.id.top_right, waveF); 
    ft.add(R.id.bottom_left, lightF); 
    ft.add(R.id.bottom_right, keyboardF);  
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
    ft.commit(); 
    getSupportFragmentManager().executePendingTransactions(); 

如果你不想靜態片段不引用它們在XML中的。

+0

非常感謝 - 現在我想我會理解如何使用片段:) – pmedia

0

Android有一個美妙的API文檔。它清楚地解釋了片段類的生命週期和方法。希望這可以幫助。 Fragments Documentation