我有一个自定义ListView this是我正在使用的 ListView,它在屏幕上显示一些数据,非常简单。现在我需要为显示的数据 View 设置主题。我这样做的方法是保存 key, value
到 SQLite 适配器,我不想使用 SharedPrefs,这需要一个很长的过程来读取超过 120 个键!并且 UI 滞后很多,所以我想让我们创建一个异步 setBackground
这就是我整理的内容。
public static HashMap<String, String> lruCache = new HashMap<>();
我缓存哈希集中的所有键
然后我创建了一个方法来检查 key 是否存在,如果不存在,则使用 AsyncTask 获取 key
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 数据库,这样我总是会得到一个键另一次。
问题就出在这里。它不会为适配器中的所有选项卡设置主题。
如您所见,它仅以第三个适配器项目为主题,但是当我上下滚动时,位置会发生变化。所以它不会改变第三个,它会变成第五个,你明白了,有人知道我该如何解决这个问题吗?我已经调试了大约 5 天,尝试了各种方法似乎无法修复它。
黑色是 setBackgroundColor
后所有项目的外观。已经完成了。白色是使用 XML 布局应用的默认颜色。
这就是我在适配器上的调用方式。
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();
}
}
但是还是和以前一样。
这是目录转储:
最佳答案
This works if I just set the color from the database and skip the async bit. But when I use async it doesn't work.
发生这种情况是因为您的 AsyncTask
无法在 UIThread 上工作,因此当结果返回时,它不会重绘
您的项目。为此,您需要使用 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;
}
关于java - ListView 适配器异步操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54715709/