Android fragments 观察ListView当前项中的LiveData

Android fragments 观察ListView当前项中的LiveData,android-fragments,android-listview,android-adapter,android-livedata,android-viewmodel,Android Fragments,Android Listview,Android Adapter,Android Livedata,Android Viewmodel,基本上,我想检索从当前ListViewItem生成的int(score)并将其分配回ListView中的具体TextView。我正在使用SharedViewModel和LiveData,但当我观察到什么都没有发生时。我使用的是Nav架构组件和单个活动。如果有人帮助,我会很高兴。谢谢你,这里有一些代码 公共类ListFrag扩展片段{ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onA

基本上,我想检索从当前ListViewItem生成的int(score)并将其分配回ListView中的具体TextView。我正在使用SharedViewModel和LiveData,但当我观察到什么都没有发生时。我使用的是Nav架构组件和单个活动。如果有人帮助,我会很高兴。谢谢你,这里有一些代码

公共类ListFrag扩展片段{

@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();
            }
        }
    });
}
}


当我尝试将TextView中的LiveData从ListView中分配出去时,它是有效的。但是当我尝试这样做时,不会发生任何事情(没有错误也没有结果)。

在适配器内部,您没有做任何事情来更新您的LiveData

适配器充当数据之间的桥梁(在您的情况下,您传递到适配器中的字符串数组),以及
列表视图
(在您的示例中,
myListView
)。对
列表视图的任何更改都需要遵循以下步骤:

  • 对数据本身进行所需的更改
  • 将此新数据传递给适配器
  • 适配器更新列表视图
我编写了一些示例代码:

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);
            }
        });
    }
}
公共类ListFrag扩展片段{
@凌驾
已创建ActivityState上的公共无效(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
//只创建和设置一次适配器。不要在observer、for循环等中创建或设置新适配器。
itemAdapter=新的itemAdapter(getActivity(),items,bushido,description,s,finalScore);
myListView.setAdapter(itemAdapter);
model=ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getCurrentScore().observe(getViewLifecycleOwner(),new Observer()){
@凌驾
公共void onChanged(@Nullable Integer s){
更新项目(项目,武士道,描述,s);
}
});
}
}
我不知道
finalscorre
应该是什么,所以我假设这是存储您提到的最终分数的文本视图,所有列表视图项都应该具有相同的值。如果不是这样,请在问题中澄清

另外请注意,虽然此解决方案足以解决您提到的特定问题,但它们还有一些其他可以改进的地方:

  • 使用
    RecyclerView
    而不是
    ListView
  • 与其维护多个
    字符串[]
    ,不如定义一个表示该项的POJO,并使用一个数组

此外,在google示例中检查这一点也会有所帮助。

您将从适配器获取项目视图,并直接更新它们。正确的方法是将更新的数据传递给适配器,并通过调用
.notifyDataSetChanged()
向适配器发出更新其内容的信号。如果你需要更详细的答案,你应该展示你的适配器实现。@SanlokLee我做了一些更改,但仍然不起作用。也许我有一些不知道的错误想法。我愿意接受新的建议。现在它起作用了:)。感谢你的时间伙伴。是的,现在我将尝试找出如何只更新单个视图。我已经尝试过一些废话:D。
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);
            }
        });
    }
}