[英]Display Image in Listview with AsyncTask
I am trying to display images in a listview with AsyncTask but I am getting an error. 我正在尝试使用AsyncTask在列表视图中显示图像,但出现错误。 Saying...
说...
Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
尝试在空对象引用上调用虚拟方法'java.lang.String java.lang.Object.toString()'
This is error is happening on 这是发生错误
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString();
}
And 和
LoadImage loadImage = new LoadImage(imageView);
Bitmap bitmap = loadImage.doInBackground();
Here is LoadImage.java 这是LoadImage.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Environment;
import android.view.View;
import android.widget.ImageView;
import java.io.File;
/**
* Created by Yudii on 27/05/2016.
*/
class LoadImage extends AsyncTask<Object, Void, Bitmap>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString();
}
@Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + path);
if (file.exists()) {
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if (!imv.getTag().toString().equals(path)) {
/* The path is not same. This means that this
image view is handled by some other async task.
We don't do anything and return. */
// return;
}
if(result != null && imv != null){
imv.setVisibility(View.VISIBLE);
imv.setImageBitmap(result);
}else{
imv.setVisibility(View.GONE);
}
}
}
And here is CustomList.java 这是CustomList.java
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomList extends ArrayAdapter<String>{
private final Activity context;
private final Integer[] imageId;
public CustomList(Activity context,
String[] web, Integer[] imageId) {
super(context, R.layout.list_single, web);
this.context = context;
this.imageId = imageId;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_single, null, true);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
LoadImage loadImage = new LoadImage(imageView);
Bitmap bitmap = loadImage.doInBackground();
imageView.setImageResource(imageId[position]);
return rowView;
}
}
And here is MainActivity.java 这是MainActivity.java
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
ListView list;
String[] web = {
"Google Plus",
"Twitter",
"Tall",
};
Integer[] imageId = {
R.drawable.gggggggggg,
R.drawable.hhhhhhhhhh,
R.drawable.ttttttttttt
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomList adapter = new
CustomList(MainActivity.this, web, imageId);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MainActivity.this, "You Clicked at " +web[+ position], Toast.LENGTH_SHORT).show();
}
});
}
}
You need to change loadImage.execute();
您需要更改
loadImage.execute();
instead of Bitmap bitmap = loadImage.doInBackground();
而不是
Bitmap bitmap = loadImage.doInBackground();
Why do you need AsyncTask? 为什么需要AsyncTask? Try to use library Picasso and open images by one string:
尝试使用Picasso库并按一个字符串打开图像:
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + path);
Picasso.with(context).load(file).into(imageView);
Bitmap objects are very weight and you need to clean memory after each Bitmap image for prevent OutOfMemoryError. 位图对象非常重,您需要在每个位图图像之后清理内存,以防止OutOfMemoryError。 I recommend you to use libraries.
我建议您使用库。
Add this in your dependencies :- 将此添加到您的依赖项中:
compile 'com.squareup.picasso:picasso:2.5.2'
and then load your image :- 然后加载您的图像:-
Picasso.with(this)
.load(drawerImage) // ImagePath
.placeholder( R.mipmap.download)
.error( R.mipmap.add_photo)
.into(imageDrawerView); //ImageView
1,Reason: 1,原因:
As I see, in your getView
function: 如我所见,在您的
getView
函数中:
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
// You need to set tag to your image view
// Ex: imageView.setTag("your_image_file_path") below this line
your imageView
has no tag so the below code will get NullPointerException
. 您的
imageView
没有标签,因此以下代码将获得NullPointerException
。
public LoadImage(ImageView imv) {
this.imv = imv;
this.path = imv.getTag().toString(); // Crashed here.
}
Also, I see in your getView
function has this code: 另外,我在您的
getView
函数中看到了以下代码:
imageView.setImageResource(imageId[position]);
That means "your ImageView
will set resource corresponding to defined imageId
array". 这意味着“您的
ImageView
将设置与定义的imageId
数组相对应的资源”。 So you no need AsyncTask
class, let remove it and change your getView like below: 因此,您不需要
AsyncTask
类,请删除它并按如下所示更改getView:
@Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView= inflater.inflate(R.layout.list_single, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
// Remove below code
// LoadImage loadImage = new LoadImage(imageView);
// Bitmap bitmap = loadImage.doInBackground();
imageView.setImageResource(imageId[position]);
return rowView;
}
Your Asynctask
class is needed whenever you use path of image file, not drawable resources. 每当使用图像文件而不是可绘制资源的路径时,都需要
Asynctask
类。
2, Improvement: 2,改进:
You can learn more about ViewHolder pattern
when using ListView
, RecyclerView
to improve performance, from Google Search . 当您使用
ListView
, RecyclerView
来提高性能时,可以从Google搜索中了解有关ViewHolder pattern
更多信息。 Below is an example with your current code: 以下是当前代码的示例:
@Override
public View getView(int position, View view, ViewGroup parent) {
View holder = null;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(R.layout.list_single, parent, false);
holder.imageView = (ImageView) view.findViewById(R.id.img);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.imageView.setImageResource(imageId[position]);
return view;
}
static class ViewHolder { // should be static class
ImageView imageView;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.