【问题标题】:Room database error while deleting row onclick删除行时房间数据库错误 onclick
【发布时间】:2018-03-07 18:20:55
【问题描述】:

我已将room SQLite 数据库定义为:

@Database(entities = {PlaceSaved.class},version = 1)
public abstract class PlaceDatabase extends RoomDatabase {

    public abstract DatabaseInterface databaseInterface();

    @Override
    protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config) {
        return null;
    }

    @Override
    protected InvalidationTracker createInvalidationTracker() {
        return null;
    }

}

定义在:

@Entity
public class PlaceSaved {

  @PrimaryKey(autoGenerate = true)
  private int id;

  @ColumnInfo(name = "time")
  private String time;

  @ColumnInfo(name="title")
  private String title;

  public PlaceSaved(){

  }

  public PlaceSaved(String time, String title) {
    this.time = time;
    this.title = title;
  }

  public String getTime() {
    return time;
  }

  public void setTime(String time) {
    this.time = time;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }
}

对应的DAO是:

@Dao
public interface DatabaseInterface {
  @Query("SELECT * FROM placesaved")
  List<PlaceSaved> getAllItems();

  @Insert
  void insertAll(PlaceSaved... todoListItems);
  @Delete
  public void delete(PlaceSaved... todoListItems);
  @Update
  public void update(PlaceSaved...todoListItems);
}

这些数据通过 recyclerview 显示,每个项目布局定义为:

  <TextView
     android:id="@+id/secondLine"/>
   <TextView
    android:id="@+id/firstLine"/>
 <ImageButton
    android:id="@+id/delicon"/>

现在,我想用这个deliconImageButton来删除对应的条目。 因此,我尝试将其放入我的适配器中(注意:已更新,请参阅末尾的更新代码):

public class PlacesAdapter extends RecyclerView.Adapter<PlacesAdapter.ViewHolder> {

    //PlaceDatabase db;
    List<PlaceSaved> items;

    public PlacesAdapter(List<PlaceSaved> items) {
        this.items = items;
    }

    @Override
    public PlacesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.places_list_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(PlacesAdapter.ViewHolder holder, final int position) {

        holder.name.setText(items.get(position).getTitle());
        holder.time.setText(items.get(position).getTime());
//        holder.delbutton.setClickable(true);
        holder.delbutton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
          removeItem(items);
        }
      });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder{
        public TextView name;
        public TextView time;
        public ImageButton delbutton;

        public ViewHolder(View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.secondLine);
            time= itemView.findViewById(R.id.firstLine);
            delbutton = itemView.findViewById(R.id.delicon);

        }
    }
    private void removeItem(PlaceSaved infoItem){
      PlaceSaved placeSaved = new PlaceSaved();
      placeSaved.delete(infoItem);
    }
}

并且recyclerview被称为:(**注意:onCreate更新并在最后发布)

public class PlacesActivity extends AppCompatActivity {
    FloatingActionButton fab, fab1, fab2, fab3;
    LinearLayout fabLayout1, fabLayout2, fabLayout3;
    boolean isFABOpen=false;
    View fabBGLayout;
  public static RecyclerView recyclerView;
  public static RecyclerView.Adapter adapter;
  List<PlaceSaved> items;

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

    //whenever the activity is started, it reads data from database and stores it into
    // local array list 'items'
    final PlaceDatabase db = Room.databaseBuilder(getApplicationContext(), PlaceDatabase.class, "production")
        .build();

    //it is very bad practice to pull data from Room on main UI thread,
    // that's why we create another thread which we use for getting the data and displaying it
    Runnable r = new Runnable() {
      @Override
      public void run() {
        items = db.databaseInterface().getAllItems();
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplication()));
        adapter = new PlacesAdapter(items);
        adapter.notifyDataSetChanged();
        recyclerView.setAdapter(adapter);
      }
    };

这会产生编译时错误:

PlacesAdapter.java
Error:(43, 22) error: incompatible types: List<PlaceSaved> cannot be converted to PlaceSaved
Error:(68, 17) error: cannot find symbol method delete(PlaceSaved)

请帮我解决这个问题。

更新 根据 Vishu 的回答,我已将适配器更新为:

public class PlacesAdapter extends RecyclerView.Adapter<PlacesAdapter.ViewHolder> {

  private static final String TAG = "MyActivity";

  List<PlaceSaved> items;
  PlaceDatabase db;
  public PlacesAdapter(List<PlaceSaved> items, PlaceDatabase db) {
    this.items = items;
    this.db = db;
  }

    @Override
    public PlacesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View view = LayoutInflater.from(parent.getContext())
          .inflate(R.layout.places_list_item,parent,false);
      return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final PlacesAdapter.ViewHolder holder, final int position) {
      holder.name.setText(items.get(position).getTitle());
        holder.time.setText(items.get(position).getTime());
        holder.delbutton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
        removeItem(items.get(holder.getAdapterPosition()));
        }
      });
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder{
      public TextView name;
      public TextView time;
      public ImageButton delbutton;

      public ViewHolder(View itemView) {
        super(itemView);
        name = itemView.findViewById(R.id.secondLine);
        time= itemView.findViewById(R.id.firstLine);
        delbutton = itemView.findViewById(R.id.delicon);

      }
    }
    private void removeItem(PlaceSaved infoItem){
//      db.delete(infoItem);
      Log.v(TAG, "remove Item called");
    }
}

在 PlacesActivity 中:

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

    final PlaceDatabase db = Room.databaseBuilder(getApplicationContext(), PlaceDatabase.class, "production")
        .build();

    Runnable r = new Runnable() {
      @Override
      public void run() {
        items = db.databaseInterface().getAllItems();
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplication()));
        adapter = new PlacesAdapter(items, db);
        adapter.notifyDataSetChanged();
        recyclerView.setAdapter(adapter);
      }
    };

仍然给出语法错误:

Error:(71, 17) error: cannot find symbol method delete(PlaceSaved)

和 2 个警告(不是由于 Vishu 的回答,它之前就存在):

PlaceSaved.java
Warning:(11, 8) There are multiple good constructors and Room will pick the no-arg constructor. You can use the @Ignore annotation to eliminate unwanted constructors.

PlaceDatabase.java
Warning:(13, 17) Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

错误:更新:
添加db.databaseInterface().delete(infoItem); 在 removeitem 中给出:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
      at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:164)                                                                             
     at android.arch.persistence.room.RoomDatabase.beginTransaction(RoomDatabase.java:211)
     at DatabaseInterface_Impl.delete(DatabaseInterface_Impl.java:94)
     at PlacesAdapter.removeItem(PlacesAdapter.java:69)
     at PlacesAdapter.access$000(PlacesAdapter.java:20)
     at PlacesAdapter$1.onClick(PlacesAdapter.java:45)
     at android.view.View.performClick(View.java:6294)

【问题讨论】:

    标签: android android-sqlite android-room


    【解决方案1】:

    你为什么在removeItem() 中传递PlaceSaved 中的ArrayListremoveItem() 仅接受 PlaceSaved

    所以把你的 onclick 改成

    removeItem(items.get(holder.getAdapterPosition()));
    

    make holder final in 方法签名 final PlacesAdapter.ViewHolder holder 否则它不会编译。

    您在PlaceDatabase 中定义了delete,并且您正在调用PlaceSaved,这就是您得到Error:(68, 17) error: cannot find symbol method delete(PlaceSaved) 的原因

    你可以从PlacesAdapter 中传递db,就像items 一样PlacesAdapter(items, db)

    改变

    adapter = new PlacesAdapter(items);
    

    adapter = new PlacesAdapter(items, db);
    

    现在您的 PlacesAdapter 将拥有 db 实例。你可以用db.delete(infoItem)替换placeSaved.delete(infoItem);

    改变

    List<PlaceSaved> items;
    public PlacesAdapter(List<PlaceSaved> items) {
        this.items = items;
    }
    

    List<PlaceSaved> items;
    PlaceDatabase db;
    public PlacesAdapter(List<PlaceSaved> items, PlaceDatabase db) {
        this.items = items;
        this.db = db
    }
    

    并且 改变

     placeSaved.delete(infoItem);
    

    db.databaseInterface().delete(infoItem);
    

    【讨论】:

    • 嗨 Vishu,感谢您的评论。但是我仍然不明白如何传递数据库。我已经更改了现在有效的 OnClick,但 removeItem 方法仍然给出错误:错误:(69、17)错误:找不到符号方法删除(PlaceSaved)错误:任务':app:compileDebugJavaWithJavac'的执行失败。 > 编译失败;有关详细信息,请参阅编译器错误输出。
    • 更新答案!!
    • Vishu,再次感谢您的回复。更改 PlacesAdapter(items, db) 给出错误:错误:(44、19)错误:类 PlacesAdapter 中的构造函数 PlacesAdapter 不能应用于给定类型;必需:List 找到:List,PlaceDatabase 原因:实际参数列表和正式参数列表的长度不同
    • 按照答案中的描述更改构造函数
    • 嗨,非常感谢。现在,我的 removeItem 看起来像:private void removeItem(PlaceSaved infoItem){ db.delete(infoItem); Log.v(TAG, "remove Item called"); } 没有错误,但也没有删除该项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多