2016-11-30 3 views
-3

Я пытаюсь создать приложение, которое заполняет ListView из JSON, получившего одобрение. Я получаю следующее исключение, когда пытаюсь обновить список, используя notifyDataSetChanged.Обновить ListView адаптер во фрагменте из-за пределов метода onCreateView

Попытка вызвать виртуальный метод 'пустот com.example.android.Wordtrend.CustomArrayAdapter.notifyDataSetChanged()' на нулевой ссылки на объект

элемент управления ListView находится внутри фрагмента. Im использует метод onPostExecute для вызова метода обновления внутри фрагмента для обновления ArrayAdapter. UI загружает фиктивные данные, предоставленные в методе onCreateView, но не работает во время обновления.

Я новичок, поэтому любой совет будет очень полезен. Im confused, потому что 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(). ft.add (frame.getId(), mFragment) .commit(); FragmentTransaction ft = getFragmentManager(). BeginTransaction(); ft.add (frame.getId(), mFragment) .commit();

  • Затем асинхронно метод фрагмент onAttach() следуют другие, как onCreateView() и onViewCreated() будет вызван рендеринга Android.

В коде, адаптер инициализируется в onViewCreated(), так что только после того, как фрагмент вставляется и инициализируется вы будете в состоянии назвать update(). Если вы звоните по телефону update, вы получите NullPointerException, так как адаптер еще не был инициализирован.

Вам необходимо реорганизовать свой код, либо обнаружив вызов update(), когда фрагмент не включен, либо отложил обновление, либо просто вызвал обновление позже.

+0

Спасибо руппс. Как вы упомянули ранее, проблема, вызванная методом обновления, была проблемой. –

0

попытка поставить весь код внутри метода onActivityCreated()

0

использовать этот метод ниже в вашем фрагменте:

  1. dataArray.clear();
  2. данныеArray = новый ArraryList <>();
  3. dataArray = getListBynet(); получить данные из сети
  4. newAdapter = новый CustomArrayAdapter (dataArray);
  5. listView.setAdapter (newAdapter);

надеюсь, что это полезно

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); из вашего фрагмента.

Надеюсь, это поможет!

Смежные вопросы