如何实现 Asynctask 在 ArrayAdapter 中加载图像
Posted
技术标签:
【中文标题】如何实现 Asynctask 在 ArrayAdapter 中加载图像【英文标题】:How to implement Asynctask to load images in ArrayAdapter 【发布时间】:2018-06-28 20:29:33 【问题描述】:我正在开发一个课程列表应用程序,该应用程序通过 ArrayAdapter 将每个课程标题与课程图像一起加载到列表视图中,我想实现异步任务以在列表视图和 ArrayAdapter 之间加载图像,因为列表视图在滚动时会滞后,请帮帮我。
MainActivity.java
package com.emmakade.okt;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity
protected List<Course> data;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data = DataProvider.getData();
ArrayAdapter<Course> courseArrayAdapter =
new CourseArrayAdapter(this, 0, data);
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(courseArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
Course course = data.get(position);
displayDetail(course);
);
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
return true;
return super.onOptionsItemSelected(item);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == DETAIL_REQUEST_CODE)
if (resultCode == RESULT_OK)
String msg = data.getStringExtra("resultMessage");
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
class CourseArrayAdapter extends ArrayAdapter<Course>
Context context;
List<Course> objects;
public CourseArrayAdapter(Context context, int resource, List<Course> objects)
super(context, resource, objects);
this.context = context;
this.objects = objects;
@Override
public View getView(int position, View convertView, ViewGroup parent)
Course course = objects.get(position);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.course_item, null);
TextView tv = (TextView) view.findViewById(R.id.tvTitle);
tv.setText(course.getTitle());
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
iv.setImageResource(res);
return view;
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_
android:layout_
android:id="@+id/imageLogo"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:src="@drawable/academy"/>
<TextView
android:id="@+id/txtOutput"
android:layout_
android:layout_
android:text="@string/course_catalog"
android:layout_alignBottom="@+id/imageLogo"
android:layout_toEndOf="@+id/imageLogo"
android:layout_marginStart="20dp"
android:layout_marginBottom="15dp"
android:textSize="28sp" />
<ListView
android:layout_
android:layout_
android:id="@android:id/list"
android:layout_below="@+id/imageLogo"
android:layout_marginTop="10dp"
android:layout_alignParentStart="true" />
</RelativeLayout>
course_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:padding="10dp">
<ImageView
android:layout_
android:layout_
android:id="@+id/imageCourse" />
<TextView
android:layout_
android:layout_
android:id="@+id/tvTitle"
android:layout_toEndOf="@+id/imageCourse"
android:layout_marginStart="10dp"
android:textSize="18sp"/>
</RelativeLayout>
enter image description here
【问题讨论】:
【参考方案1】:我建议您使用Glide 库进行异步图像加载、缓存和显示。
添加依赖
implementation 'com.github.bumptech.glide:glide:4.5.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
在适配器中这样使用
Glide.with(this).load("url").into(imageView);
ImageView iv = (ImageView) view.findViewById(R.id.imageCourse);
int res = context.getResources().getIdentifier(
"image_" + course.getCourseNumber(), "drawable",
context.getPackageName()
);
Glide.with(this).load(res).into(iv);
【讨论】:
将库加载到我的 build.gradle 时出错。它说找不到 Gradle DSL 方法:'implementation()' 使用编译'com.github.bumptech.glide:glide:3.6.1'【参考方案2】:您可以使用 handler,因为 asynctask 将在另一个线程上工作,但您不能从另一个线程而不是主线程更新 ui。还可以考虑使用glide、picasso 之类的库。这些库可以有效地缓存图像并以更高的性能工作。
有一个Handler的例子。
Handler handler = new Handler();
handler.post(() ->
profilephoto.setImageBitmap(pp);
);
【讨论】:
复制粘贴即可。 "profilephoto" 是你的 imageview,"pp" 是你的位图。以上是关于如何实现 Asynctask 在 ArrayAdapter 中加载图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在 AsyncTask 中更新 ArrayList 的内容?