使用多线程使带有图像的 ListView 更快 (Android API 10)
Making faster ListView with images using multi-threading (Android API 10)
我搜索了答案,但 none 似乎对我的情况有所帮助。
应用最小 SDK - API 10
问题 - 带图像的 ListView 速度慢。
原因 - 数据加载在 UI 线程上(没有图像一切正常)并且可能是我获取图像资源 ID 的方式。
我有一个带有两个 TextView 和一个 ImageView 的 ListView。我使用 SQLiteAssetHelper 从插入的数据库填充 ListView 文本。
table例子:
specie_table
_id | LITHUANIAN | LATIN
0 | Paprastasis varnėnas| Sturnus vulgaris
1 | Juodasis strazdas | Turdus merula
图片加载
我将 PNG 图片保存在 drawable 文件夹中。
我从数据库中的数据中获取图片资源id:
在specie_table.db "Regulus regulus" -> getImageName(name) returns "regulus_regulus" -> getResId(name, class) returns drawable id -> setImage(ImageView, name) 设置ImageView的资源
我应该采取不同的方法吗?
List_item.xml
<ImageView
android:id="@+id/icon"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="6dip"
android:layout_marginLeft="6dip"
android:layout_marginRight="10dip"
android:src="@drawable/ic_bird_grey"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:layout_toRightOf="@id/icon"
android:paddingTop="15dp">
<TextView
android:id="@+id/firstLine"
android:layout_width="match_parent"
android:layout_height="35sp"
android:text="Lithuanian title"
android:textSize="20sp"
/>
<TextView
android:id="@+id/secondLine"
android:layout_width="match_parent"
android:layout_height="24dp"
android:text="Latin title"
android:textSize="12sp" />
</LinearLayout>
SpecieCursorAdapter.java
public class SpecieCursorAdapter extends CursorAdapter {
SpecieCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
SpecieHolder holder = null;
holder = new SpecieHolder();
holder.imgIcon = (ImageView) view.findViewById(R.id.icon);
holder.txtTitle1 = (TextView) view.findViewById(R.id.firstLine);
holder.txtTitle2 = (TextView) view.findViewById(R.id.secondLine);
String nameLT = cursor.getString(cursor.getColumnIndex(SpecieTable.LIT_COL));
String nameLOT = cursor.getString(cursor.getColumnIndex(SpecieTable.LAT_COL));
holder.txtTitle1.setText(nameLT);
holder.txtTitle2.setText(nameLOT);
setImage(holder.imgIcon, nameLOT); //this makes everything laggy but i dont know how to make it as seperate thread.
}
static class SpecieHolder
{
ImageView imgIcon;
TextView txtTitle1;
TextView txtTitle2;
}
public void setImage(ImageView mainImage, String resource){ //these methods are for getting the image resource id from String (latin name).
int id = getResId(getImageName(resource), R.drawable.class);
if(id != -1)
mainImage.setImageResource(id);
else
mainImage.setImageResource(R.drawable.ic_bird_grey);
}
public int getResId(String resourceName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resourceName);
return idField.getInt(idField);
} catch (Exception e) {
return -1;
}
}
public String getImageName(String resource){
String string = resource.toLowerCase();
string = string.replace(' ', '_');
string = string.replace(".", "");
return string;
}}
ListActivity.java
public class ListActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE = "bird info";
ListView listView;
ListActivity context = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
listView = (ListView)findViewById(R.id.listView);
Intent intent = getIntent();
Habitats habitat = Habitats.detachFrom(intent); //this is an enum type sent as String, converted back to enum.
Cursor cursor;
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
cursor = databaseAccess.getCursorByHabitat(habitat);
databaseAccess.close();
SpecieCursorAdapter adapter = new SpecieCursorAdapter(this, cursor);
listView.setAdapter(adapter);// how to seperate the image loading?
}
例子会很有帮助!我会插入任何需要的额外代码。
尝试使用 Volley HTTP 库来加快数据传输和图像加载速度。
Volley 是一个 HTTP 库,它使 Android 应用程序的网络更容易,最重要的是,速度更快。
点击这些链接
您可以使用@abhilash 建议的现有库,也可以自行实现
在 android 中,在列表视图中显示带有图像的项目是这样的(示例):
- 列表视图需要显示位置 #35 的项目
- listview 要求其适配器为位于 #35 的项目填充 listviewitemview
- listviewitemview 要么从不再可见的旧 listviewitemview 回收,要么创建新的 listviewitemview
- 每个 listviewitemview 都有一个对应的带有 imageID 的 viewHolder 和一个 bitmap-gui 元素
- listviewitemview 中的图像最初加载了一个占位符图像,该图像在图像加载完成之前一直可见。
- 适配器开始在后台加载图像(异步任务),获取带有 imageID 的 viewHolder。
- 当背景中的图像加载完成时,viewholder-gui 元素获取加载的图像。
GridView 和 ListView 的工作方式相同。
这是来自 APhotoManager. It contains a GalleryCursorFragment 的工作示例,其中包含带有嵌入式 GridCellViewHolder
的 gridview
按照@Neil 和@shelll 的建议,我使用了Glide 库。我相应地修改了我的代码:
添加到build.gradle
compile 'com.github.bumptech.glide:glide:3.7.0'
通过更改
修改了 bindView() 方法
setImage(holder.imgIcon, nameLOT);
到
int imageId = getResId(getImageName(nameLOT), R.drawable.class);
if(imageId == -1)
imageId = R.drawable.ic_bird_grey;
Glide
.with(holder.imgIcon.getContext())
.load(imageId)
.into(holder.imgIcon);
我搜索了答案,但 none 似乎对我的情况有所帮助。 应用最小 SDK - API 10
问题 - 带图像的 ListView 速度慢。
原因 - 数据加载在 UI 线程上(没有图像一切正常)并且可能是我获取图像资源 ID 的方式。
我有一个带有两个 TextView 和一个 ImageView 的 ListView。我使用 SQLiteAssetHelper 从插入的数据库填充 ListView 文本。
table例子:
specie_table
_id | LITHUANIAN | LATIN
0 | Paprastasis varnėnas| Sturnus vulgaris
1 | Juodasis strazdas | Turdus merula
图片加载
我将 PNG 图片保存在 drawable 文件夹中。
我从数据库中的数据中获取图片资源id:
在specie_table.db "Regulus regulus" -> getImageName(name) returns "regulus_regulus" -> getResId(name, class) returns drawable id -> setImage(ImageView, name) 设置ImageView的资源
我应该采取不同的方法吗?
List_item.xml
<ImageView
android:id="@+id/icon"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="6dip"
android:layout_marginLeft="6dip"
android:layout_marginRight="10dip"
android:src="@drawable/ic_bird_grey"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:layout_toRightOf="@id/icon"
android:paddingTop="15dp">
<TextView
android:id="@+id/firstLine"
android:layout_width="match_parent"
android:layout_height="35sp"
android:text="Lithuanian title"
android:textSize="20sp"
/>
<TextView
android:id="@+id/secondLine"
android:layout_width="match_parent"
android:layout_height="24dp"
android:text="Latin title"
android:textSize="12sp" />
</LinearLayout>
SpecieCursorAdapter.java
public class SpecieCursorAdapter extends CursorAdapter {
SpecieCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
SpecieHolder holder = null;
holder = new SpecieHolder();
holder.imgIcon = (ImageView) view.findViewById(R.id.icon);
holder.txtTitle1 = (TextView) view.findViewById(R.id.firstLine);
holder.txtTitle2 = (TextView) view.findViewById(R.id.secondLine);
String nameLT = cursor.getString(cursor.getColumnIndex(SpecieTable.LIT_COL));
String nameLOT = cursor.getString(cursor.getColumnIndex(SpecieTable.LAT_COL));
holder.txtTitle1.setText(nameLT);
holder.txtTitle2.setText(nameLOT);
setImage(holder.imgIcon, nameLOT); //this makes everything laggy but i dont know how to make it as seperate thread.
}
static class SpecieHolder
{
ImageView imgIcon;
TextView txtTitle1;
TextView txtTitle2;
}
public void setImage(ImageView mainImage, String resource){ //these methods are for getting the image resource id from String (latin name).
int id = getResId(getImageName(resource), R.drawable.class);
if(id != -1)
mainImage.setImageResource(id);
else
mainImage.setImageResource(R.drawable.ic_bird_grey);
}
public int getResId(String resourceName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resourceName);
return idField.getInt(idField);
} catch (Exception e) {
return -1;
}
}
public String getImageName(String resource){
String string = resource.toLowerCase();
string = string.replace(' ', '_');
string = string.replace(".", "");
return string;
}}
ListActivity.java
public class ListActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE = "bird info";
ListView listView;
ListActivity context = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
listView = (ListView)findViewById(R.id.listView);
Intent intent = getIntent();
Habitats habitat = Habitats.detachFrom(intent); //this is an enum type sent as String, converted back to enum.
Cursor cursor;
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
cursor = databaseAccess.getCursorByHabitat(habitat);
databaseAccess.close();
SpecieCursorAdapter adapter = new SpecieCursorAdapter(this, cursor);
listView.setAdapter(adapter);// how to seperate the image loading?
}
例子会很有帮助!我会插入任何需要的额外代码。
尝试使用 Volley HTTP 库来加快数据传输和图像加载速度。 Volley 是一个 HTTP 库,它使 Android 应用程序的网络更容易,最重要的是,速度更快。
点击这些链接
您可以使用@abhilash 建议的现有库,也可以自行实现
在 android 中,在列表视图中显示带有图像的项目是这样的(示例):
- 列表视图需要显示位置 #35 的项目
- listview 要求其适配器为位于 #35 的项目填充 listviewitemview
- listviewitemview 要么从不再可见的旧 listviewitemview 回收,要么创建新的 listviewitemview
- 每个 listviewitemview 都有一个对应的带有 imageID 的 viewHolder 和一个 bitmap-gui 元素
- listviewitemview 中的图像最初加载了一个占位符图像,该图像在图像加载完成之前一直可见。
- 适配器开始在后台加载图像(异步任务),获取带有 imageID 的 viewHolder。
- 当背景中的图像加载完成时,viewholder-gui 元素获取加载的图像。
GridView 和 ListView 的工作方式相同。
这是来自 APhotoManager. It contains a GalleryCursorFragment 的工作示例,其中包含带有嵌入式 GridCellViewHolder
的 gridview按照@Neil 和@shelll 的建议,我使用了Glide 库。我相应地修改了我的代码:
添加到build.gradle
compile 'com.github.bumptech.glide:glide:3.7.0'
通过更改
修改了 bindView() 方法setImage(holder.imgIcon, nameLOT);
到
int imageId = getResId(getImageName(nameLOT), R.drawable.class);
if(imageId == -1)
imageId = R.drawable.ic_bird_grey;
Glide
.with(holder.imgIcon.getContext())
.load(imageId)
.into(holder.imgIcon);