简体   繁体   中英

How to save items added in RecyclerView?

I have a RecyclerView but I face some problems. Whenever I add something to the recycler view and for example switch fragments or close the app all the items in the RecyclerView disappear. 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. The app memory will stop once you close and it will shutdown once you remove it from background memory. This method is called onDestroy() .

So to prevent this, you can make use of android default local storages eg SQlite Database , Shared Preferences , Room Database

1. Sqlite database is android's offline local database which requires no internet access to store data. And data to be stored in SQlite Database should be in strings format like uri path. Storing bigger files or contents like images, audios, videos inside the SQLite database is not advisible to prevent exceptions such as;

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. 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.

Or you can make use of Online databases eg mySQL, MongoDB, Firebase Database, mariaDb etc.

Basically, RecyclerView is used in conjunction with the database like Room( Local DB ) or API( Remote DB such as 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 . As with any program, List and Array commonly used in Kotlin are, of course, volatile.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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