在RecyclerView中显示来自多个Room数据库表的数据

时间:2020-04-25 16:45:49

标签: java android android-recyclerview android-room

我是Android的新手,我不确定自己缺少什么。

我正在制作一个跟踪您的日常开支的应用程序。因此,我在房间db中有4个表:expenses,tags,expenses_tags_join和pics。费用可以有多个标签和多个图片。

我的问题是显示在一个recyclerview项目上带有三个标签的一笔费用。我使用私有List<String> tag_name属性制作了模型“ DailyExpenseModel”,但出现错误:

“无法弄清楚如何从cursor.private读取此字段。 列出tag_name;“

如果我改用private String ttag_name,那么当我遍历标签时,recyclerview适配器将产生重复的费用。

我知道我无法在onBindViewHolder内进行数据库查询(起初这似乎是最简单的解决方案),而且我还在考虑实现多种视图类型,但是我不确定在我的情况下是否需要这样做。基本上,我不知道如何将我的标签(和图片)列表从db传输到我的视图持有者。

适配器:

public class DailyCostAdapter extends RecyclerView.Adapter<DailyCostAdapter.DailyCostViewHolder> {

    // Member variable to handle item clicks
    final private DailyItemClickListener mDailyItemClickListener;

    // Class variables for the List that holds cost data and the Context
    private List<DailyExpenseModel> mDailyExpenseModelEntries;

    //  private List<TagEntry> mTagEntries;
    private Context mContext;
    private CostDatabase mDb;

    //private ImageView imgv_category;

    public DailyCostAdapter(DailyItemClickListener listener, Context context) {
        mDailyItemClickListener = listener;
        mContext = context;
    }

    /**
     * Called when ViewHolders are created to fill a RecyclerView.
     *
     * @return A new DailyCostViewHolder that holds the view for daily costs
     */
    @NonNull
    @Override
    public DailyCostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //Inflate the layout to the view
        View view = LayoutInflater.from(mContext)
                .inflate(R.layout.one_cost_item_view, parent, false);

        return new DailyCostViewHolder(view);
    }

    /**
     * Called by the RecyclerView to display data at a specified position in the Cursor.
     *
     * @param holder   The ViewHolder to bind Cursor data to
     * @param position The position of the data in the Cursor
     */
    @Override
    public void onBindViewHolder(@NonNull final DailyCostViewHolder holder, int position) {
        // Determine the values of the wanted data
        DailyExpenseModel dailyExpenseModelEntry = mDailyExpenseModelEntries.get(position);

        //individual cost on particular day
        String oneCostCategory = dailyExpenseModelEntry.getEcategory();
        String oneCostName = dailyExpenseModelEntry.getEname();
        int oneCostValue = dailyExpenseModelEntry.getEcost();
        String oneCostValueString = Helper.fromIntToDecimalString(oneCostValue);
        final int CostId = dailyExpenseModelEntry.getEid();

        List<String> oneCostTags = new ArrayList<>();
        oneCostTags.addAll(dailyExpenseModelEntry.getTtag_name());
//        oneCostTags.add(tag);

        //Set other values
        holder.tv_costDescription.setText(oneCostName);
        holder.tv_costValue.setText(currency1 + oneCostValueString + currency2);

        holder.cg_tagsDailyCost.removeAllViews();
        for (String s : oneCostTags) {
            Chip chip = new Chip(mContext);
            chip.setText(s);
            holder.cg_tagsDailyCost.addView(chip);
        }

DailyExpenseModel(绑定所有实体的数据):

public class DailyExpenseModel  {
    public int eid;
    public String ecategory;
    public String ename;
    public int ecost;
    public String edate;
    private List<String> ttag_name;
    private List<String> ppic_uri;
    private List<String> ppic_name;

    public DailyExpenseModel(int eid, String ecategory, String ename, int ecost, String edate,
                             List<String> ttag_name, List<String> ppic_uri, List<String> ppic_name) {
        this.eid = eid;
        this.ecategory = ecategory;
        this.ename = ename;
        this.ecost = ecost;
        this.edate = edate;
        this.ttag_name = ttag_name;
        this.ppic_uri = ppic_uri;
        this.ppic_name = ppic_name;
    }

    public int getEid() {
        return eid;
    }

    public String getEcategory() {
        return ecategory;
    }

    public String getEname() {
        return ename;
    }

    public int getEcost() {
        return ecost;
    }

    public String getEdate() {
        return edate;
    }

    public List<String> getTtag_name() {
        return ttag_name;
    }

    public List<String> getPpic_uri() {
        return ppic_uri;
    }

    public List<String> getPpic_name() {
        return ppic_name;
    }
}

ViewModel:

public class DailyExpensesViewModel extends ViewModel {

    private LiveData<List<DailyExpenseModel>> costs;

    public DailyExpensesViewModel(CostDatabase database, String date) {
        costs = database.dailyExpensesDao().loadEverythingForDate(date);
    }

    public LiveData<List<DailyExpenseModel>> getCosts() {
        return costs;
    }

}

Dao (为简单起见,不包括PicsEntry数据):

@Dao
public interface DailyExpensesDao {

    @Query("SELECT e.id AS eid, e.category AS ecategory, e.name AS ename, e.cost AS ecost, e.date AS edate," +
            " t.tag_name AS ttag_name FROM expenses e " +
            "LEFT JOIN expenses_tags_join et ON e.id = et.expense_id " +
            "LEFT JOIN tags t ON et.tag_id = t.tag_id WHERE edate = :date")
    LiveData<List<DailyExpenseModel>> loadEverythingForDate(String date);

}

1 个答案:

答案 0 :(得分:0)

我的解决方案非常简单。全部与@Relation注释有关:here

DailyExpenseModel (我将其重命名为DailyExpenseTagsWithPicsPojo):

public class DailyExpenseTagsWithPicsPojo {

    public DailyExpenseTagsWithPicsPojo() {
    }

    @Embedded
    public CostEntry costEntry;

    @Relation(parentColumn = "id",
            entityColumn = "tag_id",
            entity = TagEntry.class,
            projection = {"tag_name"},
            associateBy = @Junction(value = Expenses_tags_join.class,
            parentColumn = "expense_id",
            entityColumn = "tag_id"))
    private List<String> tagNames;

    @Relation(parentColumn = "id",
            entityColumn = "expense_id",
            entity = PicsEntry.class)
    private List<PicsEntry> picsEntries;


    public CostEntry getCostEntry() {
        return costEntry;
    }

    public void setCostEntry(CostEntry costEntry) {
        this.costEntry = costEntry;
    }

    public List<String> getTagNames() {
        return tagNames;
    }

    public void setTagNames(List<String> tagNames) {
        this.tagNames = tagNames;
    }

    public List<PicsEntry> getPicsEntries() {
        return picsEntries;
    }

    public void setPicsEntries(List<PicsEntry> picsEntries) {
        this.picsEntries = picsEntries;
    }

}

适配器:

 @Override
    public void onBindViewHolder(@NonNull final DailyCostViewHolder holder, int position) {
        // Determine the values of the wanted data
        DailyExpenseTagsWithPicsPojo dailyExpenseTagsWithPicsPojo = mdailyExpenseTagsWithPicsPojos.get(position);

        //individual cost on particular day
        String oneCostCategory = dailyExpenseTagsWithPicsPojo.getCostEntry().getCategory();
        String oneCostName = dailyExpenseTagsWithPicsPojo.getCostEntry().getName();
        int oneCostValue = dailyExpenseTagsWithPicsPojo.getCostEntry().getCost();
        String oneCostValueString = Helper.fromIntToDecimalString(oneCostValue);
        List<String> oneCostTags = dailyExpenseTagsWithPicsPojo.getTagNames();
        List<PicsEntry> picsEntries = dailyExpenseTagsWithPicsPojo.getPicsEntries();

        for (PicsEntry picsEntry : picsEntries) {
            String uri = picsEntry.getPic_uri();
        }

          //Set other values
        holder.tv_costDescription.setText(oneCostName);
        holder.tv_costValue.setText(currency1 + oneCostValueString + currency2);

        if (oneCostTags != null) {
            for (String s : oneCostTags) {
                Chip chip = new Chip(mContext);
                chip.setText(s);
                holder.cg_tags.addView(chip);
            }
        }
        //set holder for pics uri...

@Dao:

@Dao
public interface DailyExpensesDao {

    @Transaction
    @Query("SELECT * FROM expenses WHERE date =:date")
    LiveData<List<DailyExpenseTagsWithPicsPojo>> loadCostsWithTagsAndPics(String date);
}