Fragment中自定义Adapter报错:this.getContext()可能为空,求排查
Hey there, let's break down the issues in your code and fix them one by one. You've got a couple of small but critical mistakes that are causing the error, plus some optimizations we can make.
1. Fragment布局加载的错误
In your onCreateView method, you're inflating the layout with:
View view = inflater.inflate(R.layout.fragment_third, container, true);
The third parameter true is the problem here. When you pass true, the system immediately adds the inflated view to the container ViewGroup. But in Fragment's lifecycle, the onCreateView method returns a view that the FragmentManager will later add to the container itself. This leads to a duplicate addition, triggering an IllegalStateException.
Fix: Change the third parameter to false:
View view = inflater.inflate(R.layout.fragment_third, container, false);
2. CustomAdapter中的关键错误
Your Adapter has a few issues that are either causing crashes or incorrect behavior:
a. Incorrect super constructor call
You're calling:
super(context, R.layout.sec);
This ArrayAdapter constructor expects a data source (like your example array) if you want the parent class to handle basic data operations. Even if you're managing the data yourself, it's better to pass the array to the super constructor to avoid inconsistencies.
Fix: Update the constructor to pass your data array:
public CustomAdapter(@NonNull Context context, String[] example) { super(context, R.layout.sec, example); this.example = example; this.mContext = context; }
b. Undefined variable reference
In getView, you're using subjects[position] but your data array is named example. This will cause a compile error (if subjects isn't defined elsewhere) or a runtime crash.
Fix: Replace subjects with example:
mViewHolder.mExample.setText(example[position]);
c. Wrong ViewHolder reuse logic
You're only setting the text when convertView is null. When convertView is reused (the else branch), you don't update the text, so all reused list items will show the text from the first item they were created with.
Fix: Move the setText call outside the if-else block, so it runs every time getView is called:
if(convertView == null) { // Inflate layout and initialize ViewHolder LayoutInflater mInflator = LayoutInflater.from(mContext); convertView = mInflator.inflate(R.layout.sec, parent, false); mViewHolder.mExample = convertView.findViewById(R.id.dept_name); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } // Update text for every position, whether view is new or reused mViewHolder.mExample.setText(example[position]);
d. (Optional) Simplify LayoutInflater initialization
Instead of using getSystemService, you can use the more concise LayoutInflater.from(mContext) to get the inflater instance.
Corrected Full Code
ThirdFragment.class
public class ThirdFragment extends Fragment { private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; String[] sub = {"random1", "random2", "random3", }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout with third parameter as false View view = inflater.inflate(R.layout.fragment_third, container, false); ListView listView = view.findViewById(R.id.listviewthird); CustomAdapter adapter = new CustomAdapter(getContext(), sub); listView.setAdapter(adapter); return view; } // Rest of your Fragment code... }
CustomAdapter.class
public class CustomAdapter extends ArrayAdapter<String> { String[] example; Context mContext; public CustomAdapter(@NonNull Context context, String[] example) { super(context, R.layout.sec, example); this.example = example; this.mContext = context; } @Override public int getCount() { return example.length; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { ViewHolder mViewHolder = new ViewHolder(); if(convertView == null) { LayoutInflater mInflator = LayoutInflater.from(mContext); convertView = mInflator.inflate(R.layout.sec, parent, false); mViewHolder.mExample = convertView.findViewById(R.id.dept_name); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } // Update text for current position mViewHolder.mExample.setText(example[position]); return convertView; } static class ViewHolder { TextView mExample; } }
Why These Fixes Work
- The
inflateparameter change prevents duplicate view attachment, which is a common Fragment pitfall. - Correcting the Adapter constructor ensures the parent
ArrayAdapterhas access to your data, avoiding unexpected behavior. - Fixing the variable name and moving the
setTextcall ensures each list item displays the correct data, even when views are reused (which is crucial for performance and correct UI).
内容的提问来源于stack exchange,提问作者kk324

