Android中Fragment列表点击触发Null Pointer Exception的解决求助
问题描述
开发基于Fragment的Android应用时,点击List Fragment中的条目,应用崩溃并抛出空指针异常:
Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
尝试过同类问题的解决方案但无效,相关代码及布局如下:
Main Activity 代码
public class MainActivity extends AppCompatActivity implements ListFrag.ItemSelected { TextView tvDescription; ArrayList<String> descriptions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvDescription = (TextView) findViewById(R.id.tvDescription); descriptions = new ArrayList<>(); descriptions.add("Description for item 1"); descriptions.add("Description for item 2"); descriptions.add("Description for item 3"); } @Override public void onItemSelected(int index) { tvDescription.setText(descriptions.get(index)); } }
List Fragment 代码
public class ListFrag extends ListFragment { ItemSelected activity; public interface ItemSelected { void onItemSelected(int index); } public ListFrag() { // Required empty public constructor } @Override public void onAttach(@NonNull Context context) { super.onAttach(context); activity = (ItemSelected) context; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ArrayList<String> data = new ArrayList<>(); data.add("1.This is item 1"); data.add("2.This is item 2"); data.add("3.This is item 3"); setListAdapter(new ArrayAdapter<>( getActivity() , android.R.layout.simple_list_item_1,data)); } @Override public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) { activity.onItemSelected(position); } }
Detail Fragment 代码
public class DetailFrag extends Fragment { public DetailFrag() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_detail, container, false); } }
activity_main 布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".MainActivity"> <androidx.fragment.app.FragmentContainerView android:id="@+id/listFrag" android:name="com.example.fragmentspart1.ListFrag" android:layout_width="8dp" android:layout_height="match_parent" android:layout_weight="1" tools:layout="@layout/fragment_list" /> <androidx.fragment.app.FragmentContainerView android:id="@+id/detailFrag" android:name="com.example.fragmentspart1.DetailFrag" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="2" tools:layout="@layout/fragment_detail" /> </LinearLayout>
fragment_list 布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#FFFFFF" tools:context=".ListFrag"> <ListView android:id="@+id/lvList" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
fragment_detail 布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@color/design_default_color_secondary" tools:context=".DetailFrag"> <TextView android:id="@+id/tvDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:layout_marginRight="20dp" android:text="@string/textview" android:textColor="#FFFFFF" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout>
解决方案
问题根源
tvDescription 这个TextView存在于DetailFrag的布局文件fragment_detail.xml中,但你在MainActivity里调用findViewById(R.id.tvDescription)去查找——而MainActivity的布局activity_main.xml里并没有这个控件,所以tvDescription会被赋值为null,调用setText时自然触发空指针异常。
修复步骤
- 修改DetailFrag,添加TextView成员变量并初始化,同时提供更新文本的方法:
public class DetailFrag extends Fragment { private TextView tvDescription; public DetailFrag() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_detail, container, false); // 从Fragment自身的布局中查找TextView tvDescription = view.findViewById(R.id.tvDescription); return view; } // 提供外部调用的更新文本方法 public void updateDescription(String text) { if (tvDescription != null) { tvDescription.setText(text); } } }
- 修改MainActivity,获取DetailFrag实例,在回调中调用其更新方法:
public class MainActivity extends AppCompatActivity implements ListFrag.ItemSelected { ArrayList<String> descriptions; private DetailFrag detailFrag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取布局中已加载的DetailFrag实例 detailFrag = (DetailFrag) getSupportFragmentManager().findFragmentById(R.id.detailFrag); descriptions = new ArrayList<>(); descriptions.add("Description for item 1"); descriptions.add("Description for item 2"); descriptions.add("Description for item 3"); } @Override public void onItemSelected(int index) { // 确保Fragment已添加到Activity中再调用方法 if (detailFrag != null && detailFrag.isAdded()) { detailFrag.updateDescription(descriptions.get(index)); } } }
这样修改后,点击列表条目时,MainActivity会通知DetailFrag更新自身的TextView内容,避免了空指针问题。
内容的提问来源于stack exchange,提问作者Usama Ali
相关产品推荐
相关产品推荐

