2014-09-18 14 views
0

Google的教程應用程序(默認使用支持庫) http://developer.android.com/shareables/training/FragmentBasics.zip 包含-large屏幕的雙窗格佈局。在4/15成功編譯並運行min/target SDK後,我刪除了所有支持庫的內容,並嘗試將SDK 14/19作爲練習進行現代化。爲什麼在較新版本的Android中需要將一個片段包含在ViewGroup中?

這裏是兩個窗格佈局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <fragment android:name="com.example.HeadlinesFragment" 
       android:id="@+id/headlines_fragment" 
       android:layout_weight="1" 
       android:layout_width="0dp" 
       android:layout_height="match_parent" /> 

    <fragment android:name="com.example.ArticleFragment" 
       android:id="@+id/article_fragment" 
       android:layout_weight="2" 
       android:layout_width="0dp" 
       android:layout_height="match_parent" /> 

</LinearLayout> 

ArticleFragment被實例化,所述XML附帶的教程包裹在一個的ViewGroup:

// ArticleFragment.java 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState) { 

    // If activity recreated (such as from screen rotate), restore 
    // the previous article selection set by onSaveInstanceState(). 
    // This is primarily necessary when in the two-pane layout. 
    if (savedInstanceState != null) { 
     mCurrentPosition = savedInstanceState.getInt(ARG_POSITION); 
    } 

    // Inflate the layout for this fragment 
    return inflater.inflate(R.layout.article_view, container, false); 
} 

// res/layout/article_view.xml 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/article" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:padding="16dp" 
    android:textSize="18sp" /> 

此安排返回空當這樣的事情以後運行:getActivity().findViewById(R.id.article);

我通過不斷摸索和層次觀衆發現,該解決方案是包裹在article_view一個LinearLayout:之間

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

    <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/article" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:padding="16dp" 
     android:textSize="18sp" /> 

</LinearLayout> 

做了一些改變支持庫和現代片段實現?

更新以包括MainActivity回調ArticleFragment更新代碼:

// MainActivity.java 
public static class MainActivity extends Activity 
     implements HeadlinesFragment.OnHeadlineSelectedListener { 

    public void onArticleSelected(int position) { 
      ArticleFragment articleFrag = (ArticleFragment) 
       getFragmentManager().findFragmentById(R.id.article_fragment); 

     if (articleFrag != null) { 
      articleFrag.updateArticleView(position); 
     }... 

// ArticleFragment.java 
public void updateArticleView(int position) { 
    TextView article = (TextView) getView().findViewById(R.id.article); 
    article.setText(Ipsum.Articles[position]); 
    mCurrentPosition = position; 
} 

更新以包括堆棧跟蹤:

09-18 19:04:45.239 1291-1291/com.example.fragmentbasicsrebuild E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    java.lang.NullPointerException 
      at com.example.fragmentbasicsrebuild.ArticleFragment.updateArticleView(ArticleFragment.java:74) 
      at com.example.fragmentbasicsrebuild.MainActivity.onArticleSelected(MainActivity.java:66) 
      at com.example.fragmentbasicsrebuild.HeadlinesFragment.onListItemClick(HeadlinesFragment.java:75) 
      at android.app.ListFragment$2.onItemClick(ListFragment.java:160) 
      at android.widget.AdapterView.performItemClick(AdapterView.java:298) 
      at android.widget.AbsListView.performItemClick(AbsListView.java:1100) 
      at android.widget.AbsListView$PerformClick.run(AbsListView.java:2788) 
      at android.widget.AbsListView$1.run(AbsListView.java:3463) 
      at android.os.Handler.handleCallback(Handler.java:730) 
      at android.os.Handler.dispatchMessage(Handler.java:92) 
      at android.os.Looper.loop(Looper.java:137) 
      at android.app.ActivityThread.main(ActivityThread.java:5103) 
      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:737) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
      at dalvik.system.NativeStart.main(Native Method) 

回答

1

嗯,首先你不應該使用getActivity().findViewById(R.id.article),除非你的片段中特別試圖訪問您的Fragment層次結構之外的某個東西(這通常表明您正在做一些非常非常錯誤的事情)。

我會想象的情況是,你打電話之前getActivity().findViewById()Fragment的層次已經被添加到Activity。而不是通過Activity去的,簡單地使用你的FragmentView

@Override 
public void onViewCreated(View view, Bundle savedState) { 
    // "View view" is the view you returned in onCreateView(), 
    // and also the same view that will now be returned by 
    // calling getView(). 

    TextView articleText = (TextView) view.findViewById(R.id.article); 
} 

至於爲什麼在另一個佈局包裹它會導致它的工作?沒有線索。也許你做了別的不同,忘了?不應該有任何區別,你絕對不要包裝它在一個佈局,如果不需要。

+0

的'getActivity()'調用是通過回調主調用的方法活動,它在'onCreateView()'之後才被調用。當我用GetView()替換'getActivity()'時,我仍然得到NPE。 – jordanpg 2014-09-18 19:10:42

+0

奇怪的是,這是谷歌自己的教程,不是我的代碼:http://developer.android.com/training/basics/fragments/index.html – jordanpg 2014-09-18 19:11:25

+0

你可以發佈你在回調中做什麼?你如何到達那裏? (你如何調用活動;活動如何回調片段等)? – kcoppock 2014-09-18 20:32:06

0

靜態碎片往往有一些怪癖。 getActivity().findViewById(R.id.article);可能與onCreateView接收空容器的相同原因返回null(檢出它)。 你也許是動態創建的片段更好:(代碼http://developer.android.com/guide/components/fragments.html

FragmentManager fragmentManager = getFragmentManager() 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
fragment = new ExampleFragment(); 
fragmentTransaction.add(R.id.fragment_container, fragment); 
fragmentTransaction.commit(); 

參見Android Fragment - onCreateView - container is nullAndroid Fragment is given a null container in onCreateView()

相關問題