如何删除 item/instence MVVM

how to delete item/instence MVVM

我是编程和 Android 的新手,请问一个问题,所以我必须使用 MVVM、LiveData、RecyclerView 和 Fragments 构建一个 Android 应用程序(用于购买汽车的应用程序) . 我可以创建一个汽车实例,然后在 RecyclerView 中查看它,但是当我想删除它时,我收到以下错误:

Logcat:



    java.lang.NullPointerException: **Attempt to invoke virtual method 'void com.example.da.ViewModel.MyViewModel.deleteCar(com.example.da.Model.Car)' on a null object reference**
            at com.example.da.Adapter.RecyclerAdapter$MyViewHolder.onClick(RecyclerAdapter.java:127)
            at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:174)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:223)
            at android.app.ActivityThread.main(ActivityThread.java:7656)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
    </pre>

希望大家多多帮助me.Thanks!

<pre><code>
@Dao
public interface CarDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addCar( Car car);

    @Query("SELECT * FROM Car ORDER BY model ASC")
     LiveData<List<Car>>getAllCars();

    @Delete
    public void  deleteCar(Car car);

    @Query("DELETE FROM Car")
    void deleteAll();

    @Update
    void updateCar(Car car);
    
    //User
    @Insert
    void registerUser(User user);

}
</pre></code>

数据库

<pre><code>
@Database(entities = {Car.class, User.class},version =1, exportSchema = false)

public abstract class RoomDatabase extends androidx.room.RoomDatabase {

    private static RoomDatabase roomDatabase;
    private static final String databaseName="user";
    // Dao including
    public abstract CarDao carDao();
    public abstract UserDao userDao();


    public static synchronized RoomDatabase getUserDatabase(Context context)
    {
        if (roomDatabase==null)
        {
            roomDatabase= Room.databaseBuilder(context, RoomDatabase.class,databaseName)
                    .fallbackToDestructiveMigration()
                    .build();
        }
        return roomDatabase;
</pre></code>

存储库

<pre><code>

public class Repository {
   private CarDao carDao;
   private LiveData<List<Car>>getAllCars;

    public Repository(Application application)
    {
        RoomDatabase db = RoomDatabase.getUserDatabase(application);
        carDao=db.carDao();
        getAllCars=carDao.getAllCars();

    }
    //CarDao methods
    public void addCar( Car car)
    {
       new newAsyncTask(carDao).execute(car);

    }

    private static class newAsyncTask extends AsyncTask<Car, Void, Void>{
        private CarDao myAsyncDao;

        newAsyncTask(CarDao carDao){
            myAsyncDao=carDao;
        }

        @Override
        protected Void doInBackground(Car... cars) {
            myAsyncDao.addCar(cars[0]);
            return null;
        }
    }

    public void updateCar( Car car)
    {
        new updateAsyncTask(carDao).execute(car);

    }

    private static class updateAsyncTask extends AsyncTask<Car, Void, Void>{
        private CarDao myAsyncDao;

        updateAsyncTask(CarDao carDao){
            myAsyncDao=carDao;
        }

        @Override
        protected Void doInBackground(Car... cars) {
            myAsyncDao.updateCar(cars[0]);
            return null;
        }
    }

    public void deleteCar( Car car)
    {
        new deleteAsyncTask(carDao).execute(car);

    }

    private static class deleteAsyncTask extends AsyncTask<Car, Void, Void>{
        private CarDao myAsyncDao;

        deleteAsyncTask(CarDao carDao){
            myAsyncDao=carDao;
        }

        @Override
        protected Void doInBackground(Car... cars) {
            myAsyncDao.deleteCar(cars[0]);
            return null;
        }
    }
</pre></code>

回收器适配器

<pre><code>
    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

   private List<Car>list;
    Context context;
   private MyViewModel myViewModel;
   
    public RecyclerAdapter(List<Car> list) {
        this.list = list;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.car_item,parent,false);
        MyViewHolder myViewHolder = new MyViewHolder(view);
        context=parent.getContext();
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Car car = list.get(position);
        holder.tvModel.setText(car.getCarModel());
        holder.tvColor.setText(car.getCarColor());
        holder.tvDpl.setText(car.getCarDpl());
        holder.tvDescription.setText(car.getCarDescription());
        holder.tvPrice.setText(car.getCarPrice());
    }

    @Override
    public int getItemCount() {
        if(list !=null)
        {
            return list.size();
        }
        else return 0;
    }

   public void setData(List<Car>list){
       this.list=list;
       notifyDataSetChanged();
   }

    // generate ViewHolder
    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView tvModel;
        TextView tvColor;
        TextView tvDpl;
        TextView tvDescription;
        TextView tvPrice;
        Button btnDelete;

        // Constructor of ViewHolder
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            // Inflate the views
            tvModel=itemView.findViewById(R.id.model);
            tvColor=itemView.findViewById(R.id.color);
            tvDescription=itemView.findViewById(R.id.description);
            tvDpl=itemView.findViewById(R.id.dpl);
            tvPrice=itemView.findViewById(R.id.price);
            btnDelete=itemView.findViewById(R.id.btn_delete);

            // Listener for Delete button
            btnDelete.setOnClickListener(this);
            btnDelete.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {


                    CreateAlertDialoge();

                }
            });

        }

        private void CreateAlertDialoge()
        {
            AlertDialog.Builder builder =new AlertDialog.Builder(context);
            builder.setMessage("Are you sure to delete");
            builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    Car car = new Car();
                    int ID=list.get(getAdapterPosition()).getCarId();
                    car.setCarId(ID);
                   // if (car==null){
                   //     return;
                   // }

                   //MainActivity.roomDatabase.carDao().deleteCar(car);

                   myViewModel.deleteCar(car);

                    MainActivity.fragmentManager.beginTransaction().replace(R.id.container,new BaseFragment(),null).commit();

                    Toast.makeText(context, "Yes", Toast.LENGTH_SHORT).show();
                }
            });
            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(context, "no", Toast.LENGTH_SHORT).show();

                }
            });
            builder.create();
            builder.show();
        }

        @Override
        public void onClick(View v)
        {
            Car car = new Car();
            int ID=list.get(getAdapterPosition()).getCarId();
            car.setCarId(ID);

            //MainActivity.roomDatabase.carDao().deleteCar(car);
           myViewModel.deleteCar(car);
            MainActivity.fragmentManager.beginTransaction().replace(R.id.container,new BaseFragment(),null).commit();
        }
    }


}
</pre></code>

ViewModel

<pre><code>
    public class MyViewModel extends AndroidViewModel {
   private Repository repository;
   private LiveData<List<Car>>getAllCars;

    public MyViewModel(@NonNull Application application) {
        super(application);
        repository=new Repository(application);
        getAllCars=repository.getAllCars();
    }
   public  LiveData<List<Car>>getGetAllCars(){
        return getAllCars;
    }

    public void addCar( Car car)
    {
        repository.addCar(car);
    }
    public void updateCar(Car car){
        repository.updateCar(car);
    }
    public void registerUser( User user)
    {
        repository.registerUser(user);
    }

    public void  deleteCar(Car car)
    {
        repository.deleteCar(car);
    }
    public void deleteAll(){
        repository.deleteAll();
    }

}
</pre></code>

这里的主要问题是 RecyclerAdapter 中的 myViewModel 从未设置过值。您可以在实例化 RecyclerAdapter 时传递 ViewModel 的实例。然而,这被认为是一个坏主意。

更好的方法是创建一个从 RecyclerAdapter 返回到您的 Fragment 的回调。参见: