2016-11-30 12 views
-3

JSONからリストビューを読み込むアプリケーションをビルドしようとしています。私はnotifyDataSetChangedを使用してリストビューを更新しようとすると、以下の例外が発生します。 NULLオブジェクト参照onCreateViewメソッド外のフラグメント内のListViewアダプタを更新します。

リストビューに 'ボイド com.example.android.Wordtrend.CustomArrayAdapter.notifyDataSetChanged()' を仮想メソッドを呼び出す

試みは、フラグメント内にあります。 ImはonPostExecuteメソッドを使用して、フラグメント内のupdateメソッドを呼び出してArrayAdapterを更新します。 UIはonCreateViewメソッドで提供されたダミーデータを読み込みますが、更新中には失敗します。

初心者ですから、アドバイスが非常に役に立ちます。 ArrayAdapterがnullであり、updateメソッド内でdataArrayのサイズがゼロであるため、混乱しています。

アクティビティー:クラスからの更新メソッドを呼び出す

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

パブリッククラス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 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アダプタ:onActivityCreatedメソッド内のすべてのコードを入れて

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()を挿入します。; ft.add(frame.getId()、mFragment).commit(); FragmentTransaction ft = getFragmentManager()。beginTransaction(); ft.add(frame.getId()、mFragment).commit();

  • その後、非同期、onCreateView()onViewCreated()のような他の人に続くフラグメント方法onAttach()は、Androidのレンダリングエンジンによって呼び出されます。あなたのコードで

、アダプターは断片が挿入され、初期化されるので、後にのみ、あなたがupdate()を呼び出すことができるようになり、onViewCreated()に初期化されます。 updateを前に呼び出すと、アダプターがまだ初期化されていないため、NullPointerExceptionになります。

フラグメントが挿入されていないときにupdate()の呼び出しを検出して更新を延期するか、後で更新を呼び出すだけで、コードをリファクタリングする必要があります。

+0

ありがとうrupps。以前に言及したように、私が更新メソッドを呼び出す方法が問題でした。 –

0

は試してみる()

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);を呼び出します。

希望すると助かります!

関連する問題