2013-05-20 3 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()
Система называет это, когда пришло время для фрагмента, чтобы сделать его пользовательский интерфейс в первый раз. Чтобы нарисовать пользовательский интерфейс для вашего фрагмента, вы должны вернуть представление из этого метода, который является корнем макета вашего фрагмента. Вы можете вернуть значение 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

перейдите по ссылке, вы можете точно увидеть, какой метод вызывается и когда. вы не можете установить образы в нуль, и представление не создается до тех пор, пока 'onCreateView' не будет вызван – thepoosh

+0

. Обратите внимание на мое обновление – thepoosh

4
MyFragment3 newfragment = new MyFragment3(); 

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

Вы пытаетесь получить доступ к представлению изображения, которое будет создано в onCreateView фрагмента. Когда вы вызываете newfragment.setImage();, ваше представление еще не создано, поэтому вы получаете NPE.

+0

Мне нужно установить изображение из самого первого фрагмента. Есть ли лучший способ сделать это? – wolverine

+1

попробуйте использовать 'setArgs' для передачи этого типа информации фрагменту – thepoosh

+0

какие параметры я могу передать в args? например, у меня 10 изображений изображений, Textviews ..Поэтому я думаю, что setArgs не является альтернативой – wolverine

0

Вы не можете сделать это таким образом, потому что onCreateView не была вызвана, чтобы ваш iv является недействительным. Вы можете поставить iv.setImageResource(R.drawable.penguins); в onCreateView() или, может быть, в onAttach() (я не уверен во втором).

+0

Есть ли лучший способ загрузить содержимое в фрагменте3 динамически из Frag 2? – wolverine

+0

Вы можете передать некоторые логические значения в качестве аргументов, которые будут указывать на то, что вы хотите загрузить. Например, вы можете передать пакет с isSetImage boolean, а затем в onCreateView(), в зависимости от этого флага вы можете установить свое изображение или нет. –

+0

это нормально .. Но у меня есть более 10 видов, контролируемых основной деятельностью. И у меня есть несколько ArrayLists. Я новичок в Fragments, может, пожалуйста, помогите мне с примером. – 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); 
    } 
} 
Смежные вопросы