首页 > 解决方案 > 将 RecyclerView 中的数据保存在 SharedPreferences 中

问题描述

我有一个包含预定义收入类别列表的 RecyclerView,但用户也可以添加其他类别(通过选择项目新类别)。每当用户添加新类别时,我想将其保存在 RecyclerView 中,这样他就不应该每次都添加它。

我知道我应该使用 SharedPreferences 但我不知道将它放在哪个活动中。

这是适配器。

public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder>{
private Context context;
private List<Category> lista;
private LayoutInflater layoutInflater;
private IncomeCategoryActivity activity;

private static final int CATEGORY_REQUEST=6;

public CategoryAdapter(List<Category> lista, Context context, IncomeCategoryActivity activity) {
    this.context = context;
    this.lista = lista;
    this.activity=activity;
    layoutInflater=LayoutInflater.from(context);
}

@Override
public CategoryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view=layoutInflater.inflate(R.layout.category_layout, parent, false);
    ViewHolder viewHolder=new ViewHolder(view, activity);

    return viewHolder;
}

@Override
public void onBindViewHolder(CategoryAdapter.ViewHolder holder, int position) {
    holder.imageView.setImageURI(lista.get(position).getUri());
    holder.textView.setText(lista.get(position).getCategory());
    holder.imageViewCheck.setVisibility(View.INVISIBLE);
    holder.position = position;
    holder.category=lista.get(position);
}

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

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    public ImageView imageView;
    public TextView textView;
    public ImageView imageViewCheck;
    public int position;
    public Category category;
    public IncomeCategoryActivity activity;


    public ViewHolder(View itemView, IncomeCategoryActivity activity) {
        super(itemView);
        this.activity=activity;

        imageView=itemView.findViewById(R.id.customCategoryImageView);
        textView=itemView.findViewById(R.id.customCategoryTextView);
        imageViewCheck=itemView.findViewById(R.id.customCheckImageView);

        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        String aux=textView.getText().toString();
        if(aux=="CATEGORIE NOUĂ"){
            Intent intent=new Intent(context, CustomIncomeActivity.class);
            activity.startActivityForResult(intent, CATEGORY_REQUEST);
        }
        else{
            imageViewCheck.setVisibility(View.VISIBLE);
            Intent intent=new Intent(context, AddIncomeActivity.class);
            intent.putExtra("categorie_venit", aux);
            activity.setResult(Activity.RESULT_OK, intent);
            activity.finish();
        }

    }

}

}

这是包含 RecyclerView 的活动。

public class IncomeCategoryActivity extends AppCompatActivity {
private ImageView iv_back;

private RecyclerView recyclerView;
private CategoryAdapter categoryAdapter;
private ArrayList<Category> lista;

private static final int CATEGORY_REQUEST=6;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_income_category);

    iv_back=findViewById(R.id.incomeCatBackImageView);

    loadData();
    saveIncomeCategory();
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.salary),"Salarii"));
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.allowance), "Îndemnizații"));
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.pension), "Pensii"));
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.rent), "Chirii"));
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.scholarship), "Burse"));
    lista.add(new Category(Uri.parse("android.resource://com.aplicatie_licenta.finalapp/drawable/"+R.drawable.custom), "CATEGORIE NOUĂ"));

    recyclerView=findViewById(R.id.categoryRecyclerView);
    recyclerView.setHasFixedSize(true);
    categoryAdapter=new CategoryAdapter(lista, this, this);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(categoryAdapter);

    iv_back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            finish();
        }
    });

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode==CATEGORY_REQUEST && resultCode==RESULT_OK){
            int pozitie=lista.size()-1;
            Uri uri = data.getParcelableExtra("icon");
            String category=data.getStringExtra("category");
            Category c=new Category(uri, category);
            lista.add(pozitie, c);
            categoryAdapter.notifyItemInserted(pozitie);
    }
}

private void saveIncomeCategory(){
    SharedPreferences sharedPreferences=getSharedPreferences("sharedPrefIncomeCategoryList", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor=sharedPreferences.edit();
    Gson gson=new Gson();
    String json=gson.toJson(lista);
    editor.putString("incomeCategoryList", json);
    editor.apply();
}

private void loadData(){
    SharedPreferences sharedPreferences=getSharedPreferences("sharedPrefIncomeCategoryList", Context.MODE_PRIVATE);
    Gson gson=new Gson();
    String json=sharedPreferences.getString("incomeCategoryList", null);
    Type type=new TypeToken<ArrayList<Category>>() {}.getType();
    lista=gson.fromJson(json, type);

    if(lista==null){
        lista=new ArrayList<>();
    }
}

}

我看了一些教程,并构建了 loadData() 和 saveIncomeCategory() 方法,但是当我开始活动时我的应用程序崩溃了。

标签: androidandroid-recyclerview

解决方案


通常,您希望将适配器的点击监听器挂接到父活动或片段中。在您的适配器中,您也可能会定义自己的回调。

CategoryAdapter ... {
   private OnCategoryClickedListener //Call this callback when it's clicked

   public interface OnCategoryClickedListener{
       public void onCategoryClicked(Category cat...)

}

这样,您可能会在另一个屏幕上添加列表,但您可能希望在单击屏幕时进行不同的交互。

在您的活动中,您将拥有代码

YourActivity implements CategoryAdapter.OnCategoryClickedListener {

@Override
public void onCategoryClicked(Category c){
    //This is where your shared preferences would go, save the Category or w/e it is you want
}

您还必须从适配器设置 onCategoryClickedListener,可能在创建适配器时通过构造函数。理想情况下,您希望将显示逻辑与业务逻辑分离。适配器将具有您的显示逻辑,但您的业务逻辑将在其他地方处理


推荐阅读