java - 如何使用 ViewModel 将数据加载到 fragment 内的 RecyclerView 中

标签 java android android-fragments model-view-controller android-recyclerview

我正在尝试创建一个带有底部导航的应用程序,可以在多个 fragment 之间切换。

在其中一个中,我需要在 recyclerview 中列出数据。我对 Android 相当陌生,以前从未使用过 recyclerview 或使用过 ViewModels 或 fragment ,所以我不能 100% 确定我是否以正确的方式这样做。

这是我现在拥有的:

Fragment.java

public class twoFragment extends Fragment implements LifecycleOwner {

    private twoViewModel twoViewModel;
    private RecyclerView recyclerView;
    private RecyclerViewAdapter recyclerViewAdapter;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {


        twoViewModel = new ViewModelProvider(this).get(twoViewModel.class);
        View root = inflater.inflate(R.layout.two, container, false);

        recyclerView = root.findViewById(R.id.rv_main);
        recyclerView.setHasFixedSize(true);

        twoViewModel.getUserMutableLiveData().observe(getViewLifecycleOwner(), userListUpdateObserver);


        return root;
    }

        private Observer<ArrayList<User>> userListUpdateObserver = new Observer<ArrayList<User>>() {
            @Override
            public void onChanged(ArrayList<User> userArrayList) {

                recyclerViewAdapter = new RecyclerViewAdapter(requireActivity(),userArrayList);
                recyclerView.setAdapter(recyclerViewAdapter);
            }
        };

}

ViewModel.java

public class twoViewModel  extends ViewModel {

    MutableLiveData<ArrayList<User>> userLiveData;
    ArrayList<User> userArrayList;

    public twoViewModel() {
        userLiveData = new MutableLiveData<>();

        // call your Rest API in init method
        init();
    }

    public MutableLiveData<ArrayList<User>> getUserMutableLiveData() {
        return userLiveData;
    }

    public void init(){
        populateList();
        userLiveData.setValue(userArrayList);
    }

    public void populateList(){

    User user = new User();
        user.setTitle("Darknight");
        user.setDescription("Best video ever!");

        userArrayList = new ArrayList<>();
        userArrayList.add(user);
        userArrayList.add(user);
        userArrayList.add(user);
        userArrayList.add(user);
        userArrayList.add(user);
        userArrayList.add(user);

}



}

RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    Activity context;
    ArrayList<User> userArrayList;

    public RecyclerViewAdapter(Activity context, ArrayList<User> userArrayList) {
        this.context = context;
        this.userArrayList = userArrayList;
    }


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View rootView = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
        System.out.println("onCreateViewHolder");
        return new RecyclerViewViewHolder(rootView);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

        User user = userArrayList.get(position);
        RecyclerViewViewHolder viewHolder= (RecyclerViewViewHolder) holder;

        viewHolder.txtView_title.setText(user.getTitle());
        viewHolder.txtView_description.setText(user.getDescription());
        viewHolder.imgView_icon.setImageDrawable(user.getImgIcon());
        System.out.println("onBindViewHolder");
    }

    @Override
    public int getItemCount() {
        return userArrayList.size();
    }

    class RecyclerViewViewHolder extends RecyclerView.ViewHolder {
        ImageView imgView_icon;
        TextView txtView_title;
        TextView txtView_description;

        public RecyclerViewViewHolder(@NonNull View itemView) {
            super(itemView);
            imgView_icon = itemView.findViewById(R.id.imgView_icon);
            txtView_title = itemView.findViewById(R.id.txtView_title);
            txtView_description = itemView.findViewById(R.id.txtView_description);
            System.out.println("RecyclerViewViewHolder");

        }
    }
}

问题

使用此代码,当我打开应用程序时,recyclerview。但是,当我单击 fragment 中的 EditText View 时,数据将显示在 recyclerview 中。然后,当我离开该 fragment 并返回到它时,它是空的。

我在这里做错了什么?

我在某处读到,你不应该同时使用 ViewModel 和 recyclerviews...这是如何工作的?

最佳答案

尝试将twoFragment更改为:

public class twoFragment extends Fragment {

private twoViewModel twoViewModel;
private RecyclerView recyclerView;
private RecyclerViewAdapter recyclerViewAdapter;

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {


    twoViewModel = new ViewModelProvider(this).get(twoViewModel.class);
    View root = inflater.inflate(R.layout.two, container, false);

    recyclerView = root.findViewById(R.id.rv_main);
    recyclerView.setHasFixedSize(true);
    
    recyclerViewAdapter = new RecyclerViewAdapter(requireContext());
    recyclerView.setAdapter(recyclerViewAdapter);

    twoViewModel.getUserMutableLiveData().observe(getViewLifecycleOwner(), userListUpdateObserver);


    return root;
}

    private Observer<ArrayList<User>> userListUpdateObserver = new Observer<ArrayList<User>>() {
        @Override
        public void onChanged(ArrayList<User> userArrayList) {
            recyclerView.setData(userArrayList);
        }
    };

}

并将 RecycleView 适配器更改为:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

Context context;
ArrayList<User> userArrayList = ArrayList<User>();

public RecyclerViewAdapter(Context context) {
    this.context = context;
}

public setData(ArrayList<User> userArrayList){
    userArrayList = userArrayList;
    notifyDataSetChanged();
}


@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View rootView = LayoutInflater.from(context).inflate(R.layout.item,parent,false);
    System.out.println("onCreateViewHolder");
    return new RecyclerViewViewHolder(rootView);
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

    User user = userArrayList.get(position);
    RecyclerViewViewHolder viewHolder= (RecyclerViewViewHolder) holder;

    viewHolder.txtView_title.setText(user.getTitle());
    viewHolder.txtView_description.setText(user.getDescription());
    viewHolder.imgView_icon.setImageDrawable(user.getImgIcon());
    System.out.println("onBindViewHolder");
}

@Override
public int getItemCount() {
    return userArrayList.size();
}

class RecyclerViewViewHolder extends RecyclerView.ViewHolder {
    ImageView imgView_icon;
    TextView txtView_title;
    TextView txtView_description;

    public RecyclerViewViewHolder(@NonNull View itemView) {
        super(itemView);
        imgView_icon = itemView.findViewById(R.id.imgView_icon);
        txtView_title = itemView.findViewById(R.id.txtView_title);
        txtView_description = itemView.findViewById(R.id.txtView_description);
        System.out.println("RecyclerViewViewHolder");

    }
}
}

旁注:我很确定您不需要在 fragment 上显式实现 LifeCyclerOwner,它已经实现了它。

关于java - 如何使用 ViewModel 将数据加载到 fragment 内的 RecyclerView 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67978490/

相关文章:

android - 每个 fragment 的自定义选项菜单

java - Android 将一个 fragment 导航到另一个 fragment 可以正常工作,但是看不到其他 fragment 的背景

java - 在Java中将html字符串转换为org.w3c.dom.Document

java - Android MediaPlayer 无法使用 Uri.parse(path) 播放文件名中包含 '#' 字符的文件

Android Studio 布局错误 : Unknown attribute

android - 调整默认 android 标签问题

java - Apache Camel : Control over route startup

java - 带有 Log4j2 错误的 SLF4j 无法在类类中调用工厂方法 ...RollingFileAppender 用于元素 RollingFile

java - StarActivityForResult() 导致返回 Intent 数据时强制关闭

android - 平板电脑屏幕方向更改 - 未找到 fragment ID 的 View