Отображение данных в RecyclerView из нескольких таблиц базы данных Room - PullRequest
0 голосов
/ 25 апреля 2020

Я новичок в Android, и я не уверен, что мне не хватает.

Я создаю приложение, которое отслеживает ваши ежедневные расходы. Итак, у меня есть 4 таблицы в комнате базы данных: расходы, теги, cost_tags_join и фото. Расходы могут иметь несколько тегов и несколько картинок.

Моя проблема состоит в том, чтобы отобразить, например, один счет с тремя тегами на одном элементе просмотра переработчика. Я создал модель "DailyExpenseModel" с личным атрибутом List<String> tag_name, но получил ошибку:

"Не могу понять, как прочитать это поле из курсора. Приватный список tag_name;"

Если вместо этого указать private String ttag_name, то при повторном просмотре тегов адаптер повторного просмотра создает дубликаты расходов.

Я знаю, что не могу выполнять запросы к базе данных внутри onBindViewHolder (что казалось самым простым решением при во-первых), и я также смотрел на реализацию нескольких типов представлений, но я не уверен, что это необходимо в моем случае. По сути, я не знаю, как перенести мой список тегов (и изображений) из БД в мою область просмотра.

Адаптер:

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;
    }

}

Дао (не для простоты включите данные 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 голосов
/ 30 апреля 2020

Мое решение оказалось довольно простым. Это было все о аннотациях @Relation: здесь .

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);
}
...