我正在尝试构建一个从JSON收到的ListView中填充ListView的应用程序。当我尝试使用notifyDataSetChanged更新列表视图时,我得到以下异常。
尝试调用虚方法' void com.example.android.Wordtrend.CustomArrayAdapter.notifyDataSetChanged()' 在空对象引用上
ListView位于片段内。我使用onPostExecute方法调用片段内的更新方法来更新ArrayAdapter。 UI加载onCreateView方法中提供的虚拟数据,但在更新期间失败。
我是新手,所以任何建议都会有很大帮助。我很困惑,因为ArrayAdapter为null,并且updateArray的大小在update方法中为零。
活动:
公共类ClassicActivity扩展了AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activitycategory);
getSupportFragmentManager().beginTransaction().replace(R.id.container,new ClassicFragment()).commit();
}
}
片段:
public class ClassicFragment extends Fragment {
CustomArrayAdapter adapter;
ArrayList<dataobjects> dataArray=new ArrayList<>();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
dataArray.clear();
dataArray.add(new dataobjects("word","Explanation",R.drawable.placeholder,R.raw.color_black));
dataArray.add(new dataobjects("word","Explanation",R.drawable.placeholder,R.raw.color_black));
dataArray.add(new dataobjects("word","Explanation",R.drawable.placeholder,R.raw.color_black));
View rootView=inflater.inflate(R.layout.word_list,container,false);
ListView listView=(ListView)rootView.findViewById(R.id.list);
adapter=new CustomArrayAdapter(getActivity(),dataArray,R.color.classic);
listView.setAdapter(adapter);
return rootView;
}
public void update(ArrayList<FinalData> e){
ArrayList<dataobjects> newDataArray=new ArrayList<>(); // update Adapter from JSON
for(int i=0;i<e.size();i++) {
FinalData FinalDataObject = e.get(i);
String word=FinalDataObject.getWord();
String meaning=FinalDataObject.getMeaning();
newDataArray.add(new dataobjects(word,meaning,R.drawable.placeholder,R.raw.color_black));
}
Log.d("Classic"," Size of Data"+dataArray.size()); // Shows zero but im not clearing it manually. Should be two.
dataArray.addAll(newDataArray); // Size changes to 7 as expected.
adapter.notifyDataSetChanged();
}
//从Dataprocess类中调用update方法
public class Data extends AsyncTask<String,Void,String> {
String Mdata;
@Override
protected void onPostExecute(String s) {
Mdata=s;
Dataprocess d=new Dataprocess();
d.process(Mdata);
super.onPostExecute(s);
}.....}
public class Dataprocess {
Finaldata f;
ArrayList<Finaldata> wordList=new ArrayList<>();
ClassicFragment classicfragment=new ClassicFragment();
public void process(String s ){
if(s!=null){
try {
JSONObject data = new JSONObject(s);
JSONArray word = data.getJSONArray("WordArray");
for (int i = 0; i < word.length(); i++){
JSONObject c = word.getJSONObject(i);
String word1=c.getString("word");
String meaning=c.getString("meaning");
f=new Finaldata(word1,meaning);
wordList.add(f);
}
classicfragment.update(wordList);
}catch (Exception e){
}
}
}
}
CustomArray适配器:
public class CustomArrayAdapter extends ArrayAdapter<dataobjects> {
int color;
public static MediaPlayer mediaPlayer;
static AudioManager am;
private TextToSpeech tts;
static MediaPlayer.OnCompletionListener oncom=new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
release();
}
};
public CustomArrayAdapter(Activity context, ArrayList<dataobjects> a, int color) {
super(context,0,a);
this.color=color;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View listitemview=convertView;
if(listitemview==null){
listitemview= LayoutInflater.from(getContext()).inflate(R.layout.customlayout,parent,false);
}
dataobjects currentword=getItem(position);
TextView t1=(TextView)listitemview.findViewById(R.id.textView);
TextView t2=(TextView)listitemview.findViewById(R.id.textView2);
View background1=listitemview.findViewById(R.id.back);
View background2=listitemview.findViewById(R.id.back2);
background1.setBackgroundColor(colorid);
background2.setBackgroundColor(colorid);
int ex=currentword.getImageURL();
int aud=currentword.getSound();
t1.setText(currentword.getWord());
t2.setText(currentword.getTransalation());
int colorid= ContextCompat.getColor(getContext(),color);
ImageView im1=(ImageView)listitemview.findViewById(R.id.media);
im1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
return listitemview;
}
答案 0 :(得分:0)
尝试将所有代码放在方法onActivityCreated()
中答案 1 :(得分:0)
在您的片段中使用以下方法:
希望这很有用
答案 2 :(得分:0)
嗯,您已经将适配器作为片段类的字段,因此您只需要在CustomArrayAdapter
中包含以下内容:
首先在适配器中为包含数据的ArrayList
添加字段
private ArrayList<dataobjects> data;
并在适配器构造函数中,根据您传入的内容设置该字段的值:
public CustomArrayAdapter(Activity context, ArrayList<dataobjects> a, int color) {
super(context, 0, a);
this.data = a;
this.color=color;
}
然后添加一个新方法来更改适配器中的数据:
public void setItems(ArrayList<dataobjects> items){
this.data = items;
notifyDataSetChanged();
}
您还需要覆盖getItem()
以从data
字段返回该项目。
@Override
public dataobjects getItem(int position){
return this.data.get(position);
}
然后,当您稍后更新适配器时,只需从您的片段中调用adapter.setItems(data);
即可。
希望它有所帮助!
答案 3 :(得分:0)
您的代码有点复杂,但基本上发生的情况是,当您调用update()时,片段尚未初始化。
了解Fragment生命周期。
简而言之:
您创建了一个片段(就像您的代码中使用new ClassicFragment()
)。到目前为止,只有Fragment构造函数被称为
然后使用事务将其插入屏幕,例如
FragmentTransaction ft = getFragmentManager()。beginTransaction(); ft.add(frame.getId(),mFragment).commit(); FragmentTransaction ft = getFragmentManager()。beginTransaction(); ft.add(frame.getId(),mFragment).commit();
然后,异步地,Android渲染引擎将调用片段方法onAttach()
,后跟其他类似onCreateView()
和onViewCreated()
。
在您的代码中,适配器在onViewCreated()
中初始化,因此只有在插入并初始化片段后,您才能调用update()
。如果您之前致电update
,您将获得NullPointerException
,因为适配器尚未初始化。
您需要重构代码,在片段未被引入时检测对update()的调用并推迟更新,或者稍后再调用update。