2013-05-20 52 views
4

我在從其他片段啓動一個片段時收到NullPointerException異常。我試圖在動態啓動片段後在第二個片段中調用一個方法。空片段中的指針異常

這裏是我的logcat:

05-20 09:58:31.907: E/AndroidRuntime(2585): FATAL EXCEPTION: main 
05-20 09:58:31.907: E/AndroidRuntime(2585): java.lang.NullPointerException 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at com.exercise.FragmentTest.MyFragment3.setImage(MyFragment3.java:22) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at com.exercise.FragmentTest.FragmentTestActivity$1.onClick(FragmentTestActivity.java:48) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.view.View.performClick(View.java:4204) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.view.View$PerformClick.run(View.java:17355) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.os.Handler.handleCallback(Handler.java:725) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.os.Handler.dispatchMessage(Handler.java:92) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.os.Looper.loop(Looper.java:137) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at android.app.ActivityThread.main(ActivityThread.java:5041) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at java.lang.reflect.Method.invoke(Method.java:511) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
05-20 09:58:31.907: E/AndroidRuntime(2585):  at dalvik.system.NativeStart.main(Native Method) 

和我的主要活動代碼:

public class FragmentTestActivity extends FragmentActivity{ 

    Fragment fragment; 
    Button btnFragment1, btnFragment2, btnFragment3; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     btnFragment1 = (Button)findViewById(R.id.displayfragment1); 
     btnFragment2 = (Button)findViewById(R.id.displayfragment2); 
     btnFragment3 = (Button)findViewById(R.id.displayfragment3); 

     // get an instance of FragmentTransaction from your Activity 
     FragmentManager fragmentManager = getSupportFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 

     //add a fragment 
     MyFragment myFragment = new MyFragment(); 
     fragmentTransaction.add(R.id.myfragment, myFragment); 
     fragmentTransaction.commit(); 

     btnFragment1.setOnClickListener(btnFragmentOnClickListener); 
     btnFragment2.setOnClickListener(btnFragmentOnClickListener); 
     btnFragment3.setOnClickListener(btnFragmentOnClickListener); 
    } 

    Button.OnClickListener btnFragmentOnClickListener 
    = new Button.OnClickListener(){ 

     @Override 
     public void onClick(View v) { 


      if(v == btnFragment3){ 
       MyFragment3 newfragment = new MyFragment3(); 

       FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

       // Replace whatever is in the fragment_container view with this fragment, 
       // and add the transaction to the back stack 
       transaction.replace(R.id.myfragment, newfragment); 
       transaction.addToBackStack(null); 

       // Commit the transaction 
       transaction.commit(); 
          newfragment.setImage(); 
       return; 

      } 


      // TODO Auto-generated method stub 
      Fragment newFragment = null; 

      // Create new fragment 
      if(v == btnFragment1){ 
       newFragment = new MyFragment(); 
      } 
       else if(v == btnFragment2){ 
        newFragment = new MyFragment2(); 
       } 


      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

      // Replace whatever is in the fragment_container view with this fragment, 
      // and add the transaction to the back stack 
      transaction.replace(R.id.myfragment, newFragment); 
      transaction.addToBackStack(null); 

      // Commit the transaction 
      transaction.commit(); 

      // Create new transaction 

     }}; 

} 

而且我Fragment3類是:

public class MyFragment3 extends Fragment { 
    ImageView iv; 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     View myFragmentView = inflater.inflate(R.layout.fragmentlayout3, container, false); 
     iv = (ImageView)myFragmentView.findViewById(R.id.image); 

     return myFragmentView; 
    } 
    public void setImage(){ 
     iv.setImageResource(R.drawable.penguins); 
    } 
} 

請幫我解決這個問題。

+0

是R.id.image內fragmentlayout3聲明? – Blackbelt

+0

@blackbelt,是的,我需要在基於主活動按鈕點擊的片段中顯示動態圖像.. – wolverine

回答

3

你的錯誤發生在這裏:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
newfragment.setImage(); 

和它的發生,因爲變量iv仍然null

您必須等到片段顯示(膨脹)後才能訪問已經膨脹到其中的視圖。

欲瞭解更多,請嘗試閱讀關於Fragment lifecycle

onCreateView()
系統調用這個當它的時間片段繪製它的用戶界面首次。要爲您的片段繪製UI,您必須從此方法返回一個視圖,該方法是片段佈局的根。如果片段不提供UI,則可以返回null。

創建此將使用setArgs方法並傳遞一個Bundle有關圖像信息的一種非常好的方式。

嘗試使用此代碼:

public MyFragment3 extends Fragment { 

    public static final IMAGE_RES = "IMAGE_RES"; 
    private int imageRes; 
    private ImageView iv; 

    public static MyFragment3 init(int imageRes) { 
     MyFragment3 frag = new MyFragment3(); 

     Bundle args = new Bundle(); 
     args.putInt(IMAGE_RES, imageRes); 
     frag.setArguments(args); 

     return frag; 
    } 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(SavedInstanceState); 

     imageRes = (getArguments() != null)? getArguments().getInt(IMAGE_RES) : 0; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
      View myFragmentView = inflater.inflate(R.layout.fragmentlayout3, container, false); 
     iv = (ImageView)myFragmentView.findViewById(R.id.image); 
     iv.setImageResource(imageRes); 

     return myFragmentView; 
    } 
} 
+0

當我調用Fragment3()frag = new Fragment()時,會發生什麼?它不會創建新的片段和生命週期方法,oncreate,oncreateView? – wolverine

+0

轉到附加的鏈接,您可以看到確切地調用了什麼方法以及何時。你不能將圖像設置爲null,並且在調用onCreateView'之前不會創建視圖 – thepoosh

+0

請注意我的更新 – thepoosh

4
MyFragment3 newfragment = new MyFragment3(); 

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
newfragment.setImage(); 

您嘗試將在片段的onCreateView創建訪問ImageView的。當你致電newfragment.setImage();你的看法尚未創建,因此你得到一個NPE。

+0

我必須從第一片段本身設置圖像..有沒有更好的方法來做到這一點? – wolverine

+1

嘗試使用'setArgs'將這種類型的信息傳遞給片段 – thepoosh

+0

我可以在參數中傳遞哪些參數?像,我有10個圖像瀏覽量,Textviews ..所以我認爲setArgs不是替代 – wolverine

0

你不能做這種方式,因爲onCreateView沒有被調用又那麼你iv爲空。 你可以把iv.setImageResource(R.drawable.penguins);放在onCreateView()onAttach()(我不確定第二個)。

+0

有沒有更好的方式來從Frag 2動態加載fragment3中的內容? – wolverine

+0

您可以傳遞一些布爾值作爲參數,這些參數將指示您要加載的內容。例如,您可以使用isSetImage boolean傳遞bundle,然後在onCreateView()中取決於此標誌,您可以設置或不設置圖像。 –

+0

這很好..但我有超過10視圖,由主要活動控制。我有一些ArrayLists。我是碎片新手,你能幫我一個例子嗎? – wolverine

0

使用getActivity.findViewById在片段

public class MyFragment3 extends Fragment { 
    ImageView iv; 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     View myFragmentView = inflater.inflate(R.layout.fragmentlayout3, container, false); 
     iv = (ImageView)getActivity.findViewById(R.id.image); 

     return myFragmentView; 
    } 
    public void setImage(){ 
     iv.setImageResource(R.drawable.penguins); 
    } 
}