Странное поведение при попытке получить данные с помощью SQLite в AsyncTask - PullRequest
1 голос
/ 23 января 2020

Мое приложение было очень медленным, поэтому я решил использовать AsyncTask для выполнения самых тяжелых операций внутри него, и поэтому приложение не будет слишком медленным при смене вкладок.
Но сейчас оно ведет себя очень странный путь. Позвольте мне объяснить: у меня есть ViewPager2, а внутри этого ViewPager у меня есть видоискатель. Я поместил AsyncTask внутри ViewPager, потому что это самая тяжелая операция, выполняемая во фрагменте, и в адаптере этого ViewPager я извлекаю некоторые значения из базы данных через класс DatabaseHelper, который расширяет SQLiteOpenHelper и имеет этот метод.

public Cursor getAllTasksByList(int ListID)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor c = db.rawQuery("SELECT * FROM " + Db.Tables.Tasktable.TASKS_TABLE + " WHERE " + Db.Tables.Tasktable.COL_LIST_ID + " = " + ListID, null);
        return c;
    }

Поскольку DatabaseHelper возвращает только один Курсор, я использую другой класс для организации кода, этот класс принимает Курсор в качестве аргумента и возвращает список «ListItem». Этот класс называется «FolderUtils» и содержит следующий метод (который я использую для заполнения моего RecyclerView внутри, который находится внутри моего ViewPager):

public ArrayList<TaskItem> getTasksByList(int ListID, Context context) {    
        ArrayList<TaskItem> tasks = new ArrayList<>();
        DatabaseHelper d = new DatabaseHelper(context);
        Cursor c = d.getAllTasksByList(ListID);

        while (c.moveToNext()) {
            int id = c.getInt(0);
            int listid = c.getInt(1);
            boolean checked = c.getInt(2) > 0;
            String title = c.getString(3);

            tasks.add(new TaskItem(id, listid, checked, title));
        }

        return tasks;
    }

Но здесь возникает проблема, иногда этот список пустой, но иногда он просто получает первое значение той таблицы, которую я ищу, странно, иногда он возвращает неправильные значения, и иногда он работает, только если я переместил свой ViewPager в другую позицию или просто установил несколько точек останова. Вот мой код адаптера.

@Override
    public void onBindViewHolder(@NonNull ListHolder holder, int position) {
        new LoadData(mList.get(position), holder).execute();
    }

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


    private class LoadData extends AsyncTask<Void, Void, Void> {

        private ListItem item;
        private ListHolder holder;

        public LoadData(ListItem item, ListHolder holder) {
            this.item = item;
            this.holder = holder;
        }

        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            //I set the visibility to GONE so that the user can just see the final layout and not the layout "Building" itself.
            holder.itemView.setVisibility(View.GONE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            setItems(item, holder); //setItems is for setting the UI Content.
            AttachRecycler(holder, item); //AttachRecycler creates an adapter for the recyclerview with the TaskList values, and attaches it to the recyclerview inside the ViewPager item.
            holder.itemView.setVisibility(View.VISIBLE); //Shows the finished item
        }

        @Override
        protected Void doInBackground(Void... voids) {
            SetList(item); //SetList is where it takes the values from database and adds it to the list.
            return null;
        }
    }

private void SetList(ListItem item) {
        TaskList = new ArrayList<>();

        else if (Mode == 1)
        {
            //Mode by default is 1. The line below does gets executed, however, it returns the wrong values.
            TaskList.addAll(FolderUtils.getInstance().getTasksByList(item.getID(), context));
        }

private void AttachRecycler(ListHolder holder, ListItem item)
    {
        LinearLayoutManager manager = new LinearLayoutManager(context);
        holder.recycler.setLayoutManager(manager);
        adapter = new TaskAdapter(TaskList, item.getColor(), context, item.getID());
        holder.recycler.setAdapter(adapter);

    }

Как я могу это исправить? Спасибо.

1 Ответ

0 голосов
/ 26 января 2020

Решил это сам. Решением было сделать TaskList закрытой переменной внутри класса LoadData, а не закрытой переменной всего Адаптера, это действует как локальная переменная для каждого экземпляра элемента, удаляя дубликаты в некоторых элементах.

...