简体   繁体   English

如何保存 RecyclerView 中添加的项目?

[英]How to save items added in RecyclerView?

I have a RecyclerView but I face some problems.我有一个 RecyclerView 但我面临一些问题。 Whenever I add something to the recycler view and for example switch fragments or close the app all the items in the RecyclerView disappear.每当我向回收站视图添加一些东西时,例如切换片段或关闭应用程序,RecyclerView 中的所有项目都会消失。 Would there be a way to save them?有办法拯救他们吗? Any help would be nice!你能帮忙的话,我会很高兴!

Here is some code to see if anyone needs it:这是一些代码,看看是否有人需要它:

Adapter适配器

package com.example.freetrialtracker;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class SubTrialAdapter extends RecyclerView.Adapter<SubTrialAdapter.MyViewHolder>{
    private ArrayList<SubTrial> listData;
    private Context context;
    private OnEditListener onEditListener;

    public SubTrialAdapter(Context context, ArrayList<SubTrial> list,OnEditListener onEditListener){
        this.listData=list;
        this.context=context;
        this.onEditListener=onEditListener;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View viewItem= LayoutInflater.from(parent.getContext()).inflate(R.layout.subscription_card_view,parent,false);
        return new MyViewHolder(viewItem);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

        SubTrial dataObj=listData.get(position);

        holder.nameTxt.setText(dataObj.getNamee());
        holder.startDate.setText(dataObj.getStartDate());
        holder.endDate.setText(dataObj.getEndDate());
        holder.description.setText(dataObj.getDescription());
        holder.link.setText(dataObj.getLink());

        holder.imgDelete.setOnClickListener(v->{
            listData.remove(position);
            notifyDataSetChanged();

        });
        holder.imgEdit.setOnClickListener(v->{
            onEditListener.onEditClick(listData.get(position),position);
        });


    }

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

    class MyViewHolder extends RecyclerView.ViewHolder {


        TextView nameTxt,startDate,endDate,description,link;
        ImageView imgEdit,imgDelete;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);

            nameTxt=itemView.findViewById(R.id.nameTxtId);
            startDate=itemView.findViewById(R.id.startDateTxtId);
            endDate = itemView.findViewById(R.id.endDateTxtId);
            description = itemView.findViewById(R.id.descriptionId);
            link = itemView.findViewById(R.id.linkId);
            imgEdit=itemView.findViewById(R.id.imgEdit);
            imgDelete=itemView.findViewById(R.id.imgDelete);

        }
    }



    public void editData(SubTrial listDataObj,int currentPosition){

        listData.get(currentPosition).setLink(listDataObj.getLink());
        listData.get(currentPosition).setDescription(listDataObj.getDescription());
        listData.get(currentPosition).setEndDate(listDataObj.getEndDate());
        listData.get(currentPosition).setStartDate(listDataObj.getStartDate());
        listData.get(currentPosition).setNamee(listDataObj.getNamee());
        notifyDataSetChanged();


    }

    public interface OnEditListener{
        void onEditClick(SubTrial listCurrentData, int CurrentPosition);

    }
}

Fragment分段


import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;

public class SubscriptionFragment extends Fragment implements SubscriptionDialogFragment.OnInputSelected {


    AlertDialog alertDialog;
    TextView textView1;
    RecyclerView subscriptionList;
    private FloatingActionButton mOpenDialog;
    SubTrialAdapter subscriptionAdapterList;


    ArrayList<SubTrial> subTrialArrayList;

    @Override
    public void sendInput(String name, String startDate, String endDate, String description, String link) {
        addSubscription(name, startDate, endDate, description, link);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_subscription, container, false);
        mOpenDialog = view.findViewById(R.id.fabSub);
        subTrialArrayList = new ArrayList<>();
        subscriptionList = view.findViewById(R.id.activityListSub);
        subscriptionList.setHasFixedSize(true);
        subscriptionList.setLayoutManager(new LinearLayoutManager(this.getActivity(), LinearLayoutManager.VERTICAL, false));
        textView1 = view.findViewById(R.id.textView1);
        mOpenDialog.setOnClickListener(v -> {
            SubscriptionDialogFragment dialog = new SubscriptionDialogFragment();
            dialog.setTargetFragment(SubscriptionFragment.this, 1);
            dialog.show(getFragmentManager(), "Dialog");
        });



        return view;
    }

    public void addSubscription(String strName, String strStartDate, String strEndDate, String strDescription, String strLink) {
        textView1.setText(strStartDate);
        SubTrial obj = new SubTrial();
        obj.setNamee(strName);
        obj.setStartDate(strStartDate);
        obj.setEndDate(strEndDate);
        obj.setDescription(strDescription);
        obj.setLink(strLink);

        subTrialArrayList.add(obj);
        subscriptionAdapterList = new SubTrialAdapter(this.getContext(), subTrialArrayList, this::onEditClick);
        subscriptionList.setAdapter(subscriptionAdapterList);


    }

    private void onEditClick(SubTrial listCurrentData, int currentPosition) {
        View view=LayoutInflater.from(this.getContext()).inflate(R.layout.edit_subscription,null);
        AlertDialog.Builder builderObj=new AlertDialog.Builder(view.getContext());

        EditText mSubscriptionName = view.findViewById(R.id.subscriptionName);
        EditText mStartDate = view.findViewById(R.id.startDate);
        EditText mEndDate = view.findViewById(R.id.endDate);
        EditText mDescription = view.findViewById(R.id.description);
        EditText mLink = view.findViewById(R.id.link);
        MaterialButton btnEdit=view.findViewById(R.id.btnEdit);


        mSubscriptionName.setText(listCurrentData.getNamee());
        mStartDate.setText(listCurrentData.getStartDate());
        mEndDate.setText(listCurrentData.getEndDate());
        mDescription.setText(listCurrentData.getDescription());
        mLink.setText(listCurrentData.getLink());

        ImageView closeAlert = view.findViewById(R.id.closeAlert);
        builderObj.setView(view);
        builderObj.setCancelable(false);

        closeAlert.setOnClickListener(v -> {
            alertDialog.cancel();
        });

        btnEdit.setOnClickListener(v->{
            String strName = "", strStartDate = "", strEndDate = "", strDescription = "", strLink = "";
            if (mSubscriptionName.getText() != null) {
                strName = mSubscriptionName.getText().toString();
            }

            if (strName.equals("")) {
                Toast.makeText(this.getContext(), "Please enter Subscription Name", Toast.LENGTH_LONG).show();
                return;
            }

            if (mStartDate.getText() != null) {
                strStartDate = mStartDate.getText().toString();
            }
            if (strStartDate.equals("")) {
                Toast.makeText(this.getContext(), "Please enter Start Date", Toast.LENGTH_LONG).show();
                return;
            }
            if (mEndDate.getText() != null) {
                strEndDate = mEndDate.getText().toString();
            }
            if (strEndDate.equals("")) {
                Toast.makeText(this.getContext(), "Please enter End Date", Toast.LENGTH_LONG).show();
                return;
            }
            if (mDescription.getText() != null) {
                strDescription= mDescription.getText().toString();
            }
            if (strDescription.equals("")) {
                Toast.makeText(this.getContext(), "Please enter Description", Toast.LENGTH_LONG).show();
                return;
            }
            if (mLink.getText() != null) {
                strLink = mLink.getText().toString();
            }
            if (strLink.equals("")) {
                Toast.makeText(this.getContext(), "Please enter Link", Toast.LENGTH_LONG).show();
                return;
            }

            editContact(strName, strStartDate, strEndDate, strDescription, strLink, currentPosition);

        });

        alertDialog=builderObj.create();
        alertDialog.show();

    }

    public void editContact(String strUserName, String strStartDate, String strEndDate, String strDescription, String strLink, int currentPosition){


        SubTrial obj = new SubTrial();

        obj.setNamee(strUserName);
        obj.setStartDate(strStartDate);
        obj.setEndDate(strEndDate);
        obj.setDescription(strDescription);
        obj.setLink(strLink);


        subscriptionAdapterList.editData(obj,currentPosition);
        alertDialog.cancel();


    }

}

Yes.是的。 Because once you exit the Application, the app memory is killed in the background process and opening up the app creates a new instance.因为一旦您退出应用程序,应用程序内存就会在后台进程中被杀死,并且打开应用程序会创建一个新实例。 Let's say for example, you created an editText and button which displays a Toast + text entered by the user to the user when clicked.例如,您创建了一个 editText 和一个按钮,该按钮在单击时显示用户向用户输入的 Toast + 文本。 The app memory will stop once you close and it will shutdown once you remove it from background memory.应用程序内存将在您关闭后停止,一旦您将其从后台内存中删除,它将关闭。 This method is called onDestroy() .此方法称为 onDestroy()

So to prevent this, you can make use of android default local storages eg SQlite Database , Shared Preferences , Room Database因此,为了防止这种情况,您可以使用 android 默认本地存储,例如SQlite DatabaseShared PreferencesRoom Database

1. Sqlite database is android's offline local database which requires no internet access to store data. 1. Sqlite数据库是android的离线本地数据库,不需要互联网访问来存储数据。 And data to be stored in SQlite Database should be in strings format like uri path.并且要存储在 SQlite 数据库中的数据应该是字符串格式,如 uri 路径。 Storing bigger files or contents like images, audios, videos inside the SQLite database is not advisible to prevent exceptions such as;不建议在 SQLite 数据库中存储更大的文件或内容,如图像、音频、视频,以防止出现以下异常:

FATAL EXCEPTION: main
11-06 15:16:17.199: E/AndroidRuntime(1789): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.demodbimage/com.example.demodbimage.ImagesList}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.

2. Shared Preferences is good for storing very small data values in form of keys such as strings, boolean, integers. 2. Shared Preferences 适合以字符串、布尔值、整数等键的形式存储非常小的数据值。 Take for instance, you want to prevent user from logging in after first time login is successful or you want to display dark theme next time once the user opt-in the first time.例如,您希望在第一次登录成功后阻止用户登录,或者您希望在用户第一次选择加入后下次显示深色主题。

3. Room Database is same as Sqlite database but Google recommends us to use it because it's easy to use, also provides databases syntax and very sensitive to errors. 3. Room Database 和 Sqlite 数据库一样,但是 Google 推荐我们使用它,因为它易于使用,还提供数据库语法,并且对错误非常敏感。

Or you can make use of Online databases eg mySQL, MongoDB, Firebase Database, mariaDb etc.或者您可以使用在线数据库,例如 mySQL、MongoDB、Firebase 数据库、mariaDb 等。

Basically, RecyclerView is used in conjunction with the database like Room( Local DB ) or API( Remote DB such as MySQL).基本上,RecyclerView 与 Room(本地数据库)或 API(远程数据库,如 MySQL)等数据库结合使用。
However, if you are creating a very lightweight project for your portfolio, I don't think it's a bad idea to use a datastore or sharedPrefereces .但是,如果您正在为您的投资组合创建一个非常轻量级的项目,我认为使用数据存储sharedPrefereces并不是一个坏主意。 As with any program, List and Array commonly used in Kotlin are, of course, volatile.与任何程序一样,Kotlin 中常用的ListArray当然是易变的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM