2016-11-30 49 views
-3

我試圖構建一個應用程序,該應用程序從JSON中填充ListView。當我嘗試使用notifyDataSetChanged更新列表視圖時,出現以下異常。從onCreateView方法外部更新ListView適配器

嘗試上的空對象引用

的ListView的調用虛擬方法 '無效 com.example.android.Wordtrend.CustomArrayAdapter.notifyDataSetChanged()' 是一個片段的內部。我使用onPostExecute方法來調用片段內的更新方法來更新ArrayAdapter。 UI會加載onCreateView方法中提供的虛擬數據,但在更新過程中會失敗。

我是新手,所以任何建議都會大有幫助。我感到困惑,因爲ArrayAdapter爲null,更新方法中dataArray的大小爲零。

活動:

公共類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

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

關鍵是你在哪裏以及如何調用update(),並且該部分丟失了! – rupps

+0

對不起,我的無知。編輯該帖子的其他細節。 –

回答

0

你的代碼有點複雜,但基本上發生的是,當你調用update()時,片段還沒有被初始化。

閱讀關於片段生命週期。

一言以蔽之:

  • 您創建一個片段(如在你的代碼new ClassicFragment())。到目前爲止,只有片段的構造被稱爲

  • 然後將其插入與事務在屏幕上的東西,如

    FragmentTransaction英尺= getFragmentManager()的BeginTransaction()。 (); FragmentTransaction ft = getFragmentManager()。beginTransaction();方法返回一個數組。 (frame.getId(),mFragment).commit();

  • 然後,異步,片段方法onAttach()其次是其他類似onCreateView()onViewCreated()將由Android的渲染引擎調用。

在你的代碼,該適配器在onViewCreated()初始化,片段插入並初始化,您將能夠調用update()所以之後。如果您以前撥打update,則由於適配器尚未初始化,您將收到NullPointerException

您需要重構代碼,或者在片段未被調入時檢測到對update()的調用並推遲更新,或稍後再調用update。

+0

謝謝rupps。正如你之前提到的那樣,我稱之爲更新方法是個問題。 –

0

儘量把所有的代碼)onActivityCreated方法(

0

裏面使用這個方法在下面的片段:

  1. dataArray.clear ();
  2. dataArray = new ArraryList <>();
  3. dataArray = getListBynet();從網絡獲取數據
  4. newAdapter = new CustomArrayAdapter(dataArray);
  5. listView。setAdapter(newAdapter);

希望這是有用的

0

好了,你已經在你的適配器上的片段類中的字段,所以你只需要在你的CustomArrayAdapter如下:

首先添加一個字段您的適配器爲ArrayList包含數據

private ArrayList<dataobjects> data;

和適配器的構造,設置字段的值來回回m什麼你正在傳遞:

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);即可。

希望它有幫助!