Наблюдать LiveData из ListView текущего элемента - PullRequest
0 голосов
/ 25 мая 2019

В основном я хочу получить int (оценку), сгенерированный из текущего ListViewItem, и назначить его обратно конкретному TextView в моем ListView. Я использую SharedViewModel с LiveData, но когда я наблюдаю, ничего не происходит. Я использую компонент архитектуры Nav с Single Я буду рад, если кто-то поможет. Спасибо, вот код.

открытый класс ListFrag extends Fragment {

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

    model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
        @Override
        public void onChanged(@Nullable Integer s) {

            for (int i = 0; i < myListView.getAdapter().getCount(); i++) {

                v =  myListView.getAdapter().getView(i,null, myListView);

                finalScore = v.findViewById(R.id.finalScoreView);

                    if (s != null) {
    itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
                        myListView.setAdapter(itemAdapter);
                       finalScore.setText(String.valueOf(s));

                    }
      ((BaseAdapter)myListView.getAdapter()).notifyDataSetChanged();
            }
        }
    });
}

открытый класс SharedViewModel расширяет ViewModel {

private MutableLiveData<Integer> currentScore = new MutableLiveData<>();

public LiveData<Integer> getCurrentScore(){
    return currentScore;
}

public void setCurrentScore(Integer finito) {
    currentScore.setValue(finito);

}

}

открытый класс ItemAdapter расширяет BaseAdapter {

LayoutInflater mInflater;
String[] items;
String[] bushido;
String[] description;
 TextView finalscorre;
Integer scr;

public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
    items = i;
    bushido = p;
    description = d;
    finalscorre = sc;
    scr = scc;
    mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
    return items.length;
}

@Override
public Object getItem(int i) {
    return items[i];
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public View getView(int i, View convertView, ViewGroup parent) {
    View v = mInflater.inflate(R.layout.my_listview_detail, null);
    TextView nameTextView = v.findViewById(R.id.NameTextView);
    TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
    TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
    finalscorre = v.findViewById(R.id.finalScoreView);

    String name = items[i];
    String desc = description[i];
    String bush = bushido[i];


    finalscorre.setText("Waat");
    nameTextView.setText(name);
    descriptionTextView.setText(desc);
    bushidoTextView.setText(bush);

    ItemAdapter.this.notifyDataSetChanged();

    return v;
}

}

Когда я пытаюсь назначить LiveData в TextView из ListView, это работает. Но когда я пытаюсь это сделать, ничего не происходит (без ошибок и без результата).

Ответы [ 2 ]

0 голосов
/ 26 мая 2019

Адаптеры действуют как мост между данными (в вашем случае массив строк, который вы передаете в адаптер), и ListView (в вашем случае, myListView). Любое изменение в ListView должно быть выполнено в следующем порядке:

  • внести необходимые изменения в сами данные
  • передать эти новые данные адаптеру
  • Адаптер обновляет представление списка

Я написал пример кода:

ItemAdapter

public class ItemAdapter extends BaseAdapter {

    LayoutInflater mInflater;
    String[] items;
    String[] bushido;
    String[] description;
    // TextView finalscorre; // I commented out this TextView please see the comment below
    Integer scr;

    public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
        items = i;
        bushido = p;
        description = d;
        // finalscorre = sc;
        scr = scc;
        mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public void updateItems(String[] i, String[] p, String[] d, Integer scc) {
        items = i;
        bushido = p;
        description = d;
        scr = scc;

        // notify the adapter to refresh the list view.
        notifyDataSetChanged()
    }

    @Override
    public int getCount() {
        return items.length;
    }

    @Override
    public Object getItem(int i) {
        return items[i];
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View convertView, ViewGroup parent) {
        View v = mInflater.inflate(R.layout.my_listview_detail, null);
        TextView nameTextView = v.findViewById(R.id.NameTextView);
        TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
        TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
        //finalscorre = v.findViewById(R.id.finalScoreView);
        TextView finalscorre = v.findViewById(R.id.finalScoreView);


        String name = items[i];
        String desc = description[i];
        String bush = bushido[i];


        // finalscorre.setText("Waat");
        finalscorre.setText(scr);
        nameTextView.setText(name);
        descriptionTextView.setText(desc);
        bushidoTextView.setText(bush);

        // ItemAdapter.this.notifyDataSetChanged(); Do NOT call this method inside getView

        return v;
    }
}

Фрагмент

public class ListFrag extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Create and set adapter just once. Do not create or set new adapter in observer, for loop, etc.
        itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
        myListView.setAdapter(itemAdapter);

        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable Integer s) {
                itemAdapter.updateItems(items,bushido,description,s);
            }
        });
    }
}

Мне не удалось выяснить, что должно быть finalscorre, поэтому я предположил, что это текстовое представление, в котором хранится итоговая оценка, которую вы упомянули, и все элементы представления списка должны иметь одинаковое значение. Если это не так, пожалуйста, уточните ваш вопрос.

Также обратите внимание, что хотя этого решения достаточно для решения конкретной проблемы, которую вы упомянули, есть и другие улучшения, которые можно сделать:

  • Используйте RecyclerView вместо ListView.
  • Вместо того, чтобы поддерживать несколько String[], определите POJO, которые представляют элемент и имеют один массив.

Также поможет проверка реализации этого адаптера в примере Google.

0 голосов
/ 26 мая 2019

внутри адаптера вы не делаете ничего, что обновит ваши LiveData

...