Асинхронное управление адаптером ListView - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть Custom ListView это - это ListView, который я использую, который показывает некоторые данные на экране, довольно просто.Теперь мне нужно, чтобы тема показанного представления данных.Я делаю это, сохраняя key, value на адаптере SQLite. Я не хочу использовать SharedPrefs. Это займет долгий процесс, чтобы прочитать более 120+ ключей!и сильно отстает от пользовательского интерфейса, поэтому я подумал: давайте сделаем асинхронную setBackground, вот что я собрал.

public static HashMap<String, String> lruCache = new HashMap<>();

Я кеширую все ключи в хэш-наборе

и затем я создал метод, который проверяет, существует ли ключ, если нет, он получает ключ, используя AsyncTask

public static void setBackgroundColor(View view, String key, String defaultValue) {
    String val = lruCache.get(key);
    if (val != null) {
        view.setBackgroundColor(ThemeUtils.parseColor(val));
        return;
    }
    new AsyncBackgroundColor(view).execute(key, defaultValue);
}

public static class AsyncBackgroundColor extends AsyncTask<String, String, Integer> {
    WeakReference<View> view;

    AsyncBackgroundColor(View view) {
        this.view = new WeakReference<>(view);
    }

    @Override
    protected Integer doInBackground(String... strings) {
        return ThemeUtils.getColor(strings[0], strings[1]);
    }

    @Override
    protected void onPostExecute(Integer color) {
        view.get().setBackgroundColor(color);
    }
}

, и так работает мой метод getColor.

public static int getColor(String str, String defaultValue) {
    ThemeDatabaseManager lynxDatabaseHelper = new ThemeDatabaseManager(LynxBase.getApplicationContext()).open();
    return ThemeUtils.parseColor(lynxDatabaseHelper.getString(str, defaultValue));
}

Он получает строку из моей базы данных SQlite и анализирует ее как int.Это мой getString метод

public String getString(String key, String defaultValue) {
    String cachedValue = ThemeDatabaseCache.lruCache.get(key);
    if (cachedValue != null) {
        return cachedValue;
    }
    if (!database.isOpen()) open();
    String[] columns = new String[]{ThemeDatabaseHelper.COLUMN_NAME_TITLE, ThemeDatabaseHelper.COLUMN_NAME_SUBTITLE};
    Cursor cursor = database.query(TABLE_NAME, columns, null, null, null, null, null);
    if(cursor != null) {
        cursor.moveToFirst();
        if(cursor.getCount() != 0) {
            do {
                if (!(cursor.getColumnCount() <= 1)) {
                    String k = cursor.getString(cursor.getColumnIndex(ThemeDatabaseHelper.COLUMN_NAME_TITLE));
                    String value = cursor.getString(cursor.getColumnIndex(ThemeDatabaseHelper.COLUMN_NAME_SUBTITLE));
                    if (k.equals(key)) {
                        cursor.close();
                        if (database.isOpen()) database.close();
                        ThemeDatabaseCache.lruCache.put(key, defaultValue);
                        return value;
                    }
                }
            } while (cursor.moveToNext());
        }
        cursor.close();
    }
    insertOrUpdate(key, defaultValue);
    if (database.isOpen()) database.close();
    return defaultValue;
}

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

Проблема возникает здесь.Он не отображает все вкладки в адаптере.

enter image description here

, как вы можете видеть Это только тематический 3-й элемент адаптера, но когда я прокручиваю вверхи вниз, позиция меняется.Таким образом, он не изменит 3-го, он будет 5-м, и вы поймете, кто-нибудь знает, как я могу решить эту проблему?Я отлаживал это уже около 5 дней, пробовал все виды вещей, кажется, не могу это исправить.

Черный цвет - это то, как должен выглядеть весь предмет после того, как setBackgroundColor сделан.Белый - это цвет по умолчанию, применяемый с использованием XML Layout.

Вот как я его называю на своем адаптере.

public final View getView(int i, View view, ViewGroup viewGroup){\
    ...
    view = inflate(R.layout.my_view, viewGroup, false);
    setBackground(view);
    ...
}

, и мой класс расширяет пользовательский класс, который я создал, который расширяет BaseAdapter, если это поможет!

Это то, что я пробовал в соответствии с ответом.

public static void setBackgroundColor(BaseAdapter baseAdapter, View view, String key, String defaultValue) {
    String val = lruCache.get(key);
    if (val != null) {
        Log.wtf("Lynx", "background set using cached Color.");
        view.setBackgroundColor(ThemeUtils.parseColor(val));
        baseAdapter.notifyDataSetChanged();
        return;
    }
    new AsyncBackgroundColor(baseAdapter, view).execute(key, defaultValue);
}

..

public static class AsyncBackgroundColor extends AsyncTask<String, String, Integer> {
    WeakReference<View> view;
    BaseAdapter baseAdapter;

    AsyncBackgroundColor(BaseAdapter baseAdapter, View view) {
        this.view = new WeakReference<>(view);
        this.baseAdapter = baseAdapter;
    }

    @Override
    protected Integer doInBackground(String... strings) {

        return ThemeUtils.getColor(strings[0], strings[1]);
    }

    @Override
    protected void onPostExecute(Integer color) {
        Log.wtf("Lynx", "background set using async task.");
        view.get().setBackgroundColor(color);
        if(baseAdapter != null)
        baseAdapter.notifyDataSetChanged();
    }
}

Но все так же, как и раньше.

Вот дамп Catlog:

enter image description here

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Просто в качестве дополнения.Вместо того, чтобы извлекать всю базу данных и соответствовать ThemeDatabaseHelper.COLUMN_NAME_TITLE, вам следует изменить свой запрос, чтобы получать только те записи, которые вас интересуют. Это ускорит ваши операции и позволит избежать задержек.

0 голосов
/ 17 февраля 2019

Это работает, если я просто устанавливаю цвет из базы данных и пропускаю бит асинхронности.Но когда я использую async, это не работает.

Это происходит потому, что ваш AsyncTask не работает на UIThread и, следовательно, когда результат возвращается, он не 'т redraw ваши предметы.Для этого вам необходимо уведомить адаптер о наличии новых элементов, используя myAdapter.notifyDataSetChanged();

Из кода, которым вы поделились, я полагаю, вы можете просто позвонить из своего postExecute:

public static class AsyncBackgroundColor extends AsyncTask<String, String, Integer> {
    WeakReference<View> view;
    WeakReference<Adapter> adapter;

    AsyncBackgroundColor(Adapter ad, View view) {
        this.view = new WeakReference<>(view);
        this.adapter = new WeakReference<>(ad);
    }

    @Override
    protected Integer doInBackground(String... strings) {
        return 1;
    }

    @Override
    protected void onPostExecute(Integer color) {
        view.get().setBackgroundColor(color);
        adapter.get().notifyDataSetChanged();
    }
}

Также на вашем getString() измените эту часть:

if (k.equals(key)) {
                    cursor.close();
                    if (database.isOpen()) database.close();
                    ThemeDatabaseCache.lruCache.put(key, value);
                    return value;
                }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...