Android 片段中的空指针异常
当从另一个片段开始一个片段时,我得到了NullPointerException。在动态启动片段后,我尝试在第二个片段中调用一个方法 这是我的日志:Android 片段中的空指针异常,android,android-fragments,nullpointerexception,Android,Android Fragments,Nullpointerexception,当从另一个片段开始一个片段时,我得到了NullPointerException。在动态启动片段后,我尝试在第二个片段中调用一个方法 这是我的日志: 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/AndroidRuntim
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);
}
}
请帮我克服这个问题
MyFragment3 newfragment = new MyFragment3();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
newfragment.setImage();
您正在尝试访问将在片段的onCreateView中创建的imageview。调用
newfragment.setImage()时代码>您的视图尚未创建,因此您将获得NPE。您的错误发生在此处:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
newfragment.setImage();
这是因为变量iv
仍然是null
您必须等到片段显示(膨胀)之后才能访问膨胀到其中的视图
要了解更多信息,请尝试阅读有关
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;
}
}
您不能这样做,因为还没有调用onCreateView,所以您的iv
为空。
您可以放置iv.setImageResource(R.drawable.penguins)代码>在onCreateView()
中,或者可能在onAttach()
中(我不确定第二个)。在片段中使用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);
}
}
在我的例子中,问题是因为我试图使用SwipeRefreshLayout
作为片段布局XML的根元素。一旦我添加了SwipeRefreshLayout
作为它开始工作的片段所使用的ConstraintLayout
的子级 R.id.image是否在fragmentlayout3中声明?@blackbelt,是的,我需要根据主活动按钮单击在片段中显示动态图像。我必须从第一个片段本身设置图像。。有更好的方法吗?尝试使用setArgs
将此类信息传递给碎片我可以在args中传递哪些参数?比如,我有10个图像视图,文本视图。。因此我认为setArgs不是可选的Bundle args=new Bundle();参数putInt(“图像”,i);setArguments(args)代码>在MyFragment3中,您可以调用getArguments().getInt(“image”,0)
获取传递给片段的值。当我调用Fragment3()frag=new fragment()时,会发生什么?它是否会创建新的片段和生命周期方法,如oncreate、oncreateView?转到附加的链接,您可以确切地看到调用了什么方法以及何时调用。您不能将图像设置为null,并且在调用onCreateView
之前不会创建视图。。非常感谢。如果我的视图数量少一些,它就工作得很好。但在我的例子中,我必须使用10多个基于先前片段的视图,您可以创建一个帮助器类来处理这个问题。相信我,这是正确的方式,它就是这样设计的,所有的Android示例项目都是这样构建的。嗯。。我试试这个。你能给我邮寄一些这样做的例子吗。。斯里坎。gnani@gmail.comIs有没有更好的方法从fragment3动态加载Fragment2中的内容?您可以传递一些布尔值作为参数,这些参数将指示您要加载的内容。例如,您可以使用isSetImage boolean传递捆绑包,然后在onCreateView()中根据此标志设置图像或不设置图像。这很好。。但我有超过10种观点,都是由主要活动控制的。我有一些数组列表。我是碎片新手,你能帮我举个例子吗。读了这篇文章,它应该会帮助你理解片段。。在这项工作中,他只是在连接碎片,替换。。就我而言,它正在发挥作用。。但问题只是当我试图从前面的片段调用一个方法时。