如何删除 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
的回调。参见:
我是编程和 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
的回调。参见: