Android 在没有 Picasso 的情况下将 URL 中的图像加载到自定义列表视图适配器中
Android load images from URL into custom listview adapter without Picasso
我正在尝试从 url 加载图像并且我使用过 Picasso,但是我想知道如何在没有外部库的情况下执行此操作(如果可能的话)。我知道我必须让 Asynctask 运行,但我不确定如何实现它。
这是我的 getview 代码
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if(position==0){
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.firstnews,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}else{
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.newslist,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}
return row;
}
private class AsyncDownloadTask extends AsyncTask<Object, String, Bitmap>{
private View view;
private Bitmap bitmap = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null&&view!=null){
ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
newsIcon.setImageBitmap(bitmap);
}
}
@Override
protected Bitmap doInBackground(Object... params) {
view = (View)params[0];
String uri = (String)params[1];
try{
InputStream inputStream = new URL(uri).openStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}
这是我的异步任务
更新:遇到空指针异常
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference
您可以简单地使用 java.net.URL
将图像加载到 ImageView 中,例如
ImageView loadedImage;
@override
protected Bitmap doInBackground(String... url) {
String URL_OF_IMAGE = url[0];
Bitmap bitmap = null;
try {
InputStream in = new java.net.URL(URL_OF_IMAGE).openStream();
bitmap= BitmapFactory.decodeStream(in);
} catch (Exception e) {
}
return bitmap;
}
protected void onPostExecute(Bitmap result) {
loadedImage.setImageBitmap(result);
}
但请注意,您应该扩展 AsyncTask
,第一个参数应为 String
,最后一个参数为 Bitmap
,如
private class DowmloadImage extends AsyncTask<String, Void, Bitmap>
您可以使用网络图像视图代替图像视图。它肯定会让你的生活更轻松。
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/networkImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#000000"/>
这应该替换为所需 XML 文件中的图像视图。
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new LruBitmapCache());
}
return this.mImageLoader;
}
上面的 class 还创建了一个 ImageCache,它与普通的 volley 缓存一起工作,但只缓存请求的图像。
设置图像URL。
advImage.setImageUrl("Your Image URL", AppController.getInstance().getImageLoader());
相应地调用图像加载器函数。您也可以设置默认的占位符图像。
您可以编写自己的代码。但是使用库处理与库关联的所有样板代码。除非另有原因,我还建议您使用图书馆。以下是您在编写自己的代码时需要考虑的一些样板文件。
内存管理: 外部库负责确保图像不会占用您应用的所有可用内存。 Android 位图在处理时非常注重记忆,因此最好将这部分交给图书馆。
处理activity销毁:如果您在图像下载过程中旋转phone,它将重新创建activity 然后你将需要处理取消之前的请求并重新启动它们。
取消以前的请求: 图像库的编写使得不再可见的列表视图项目不会继续下载。假设你向下滚动。那么下载第一行中的图像就没有意义了。您应该取消此类下载并开始下载新图像。图片下载器库就是为处理这些问题而编写的。
缓存: 图像库使用内存缓存和磁盘缓存来存储下载的位图。因此,他们只会下载新图像,除非它们不可用。
从 UI 线程加载大型位图: 假设您的应用包含大型位图。为了将它们加载到您的视图中,您必须首先从磁盘加载它们。您需要编写代码,以便加载它们不会阻塞主线程 UI。
加载相关图像尺寸:您的应用程序可能运行具有高屏幕密度的新Android设备或旧设备屏幕密度低。根据您的目标设备,如果您的设备不支持这样的屏幕密度,您将不需要加载全分辨率图像。通常图书馆会为您处理,
这些只是要考虑的一些样板文件。因此,我强烈建议您在图像加载部分使用一个好的库,除非它非常需要!!!
我正在尝试从 url 加载图像并且我使用过 Picasso,但是我想知道如何在没有外部库的情况下执行此操作(如果可能的话)。我知道我必须让 Asynctask 运行,但我不确定如何实现它。
这是我的 getview 代码
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if(position==0){
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.firstnews,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}else{
NewsObj currNews = news.get(position);
DataHandler dh;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.newslist,parent,false);
dh = new DataHandler();
dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
row.setTag(dh);
}else{
dh = (DataHandler)row.getTag();
}
NewsObj no = (NewsObj)this.getItem(position);
new AsyncDownloadTask().execute(row,no.getImgurl());
dh.newsTitle.setText(no.getTitle());
dh.newsDate.setText(no.getDate());
}
return row;
}
private class AsyncDownloadTask extends AsyncTask<Object, String, Bitmap>{
private View view;
private Bitmap bitmap = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null&&view!=null){
ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
newsIcon.setImageBitmap(bitmap);
}
}
@Override
protected Bitmap doInBackground(Object... params) {
view = (View)params[0];
String uri = (String)params[1];
try{
InputStream inputStream = new URL(uri).openStream();
bitmap = BitmapFactory.decodeStream(inputStream);
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}
这是我的异步任务
更新:遇到空指针异常
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference
您可以简单地使用 java.net.URL
将图像加载到 ImageView 中,例如
ImageView loadedImage;
@override
protected Bitmap doInBackground(String... url) {
String URL_OF_IMAGE = url[0];
Bitmap bitmap = null;
try {
InputStream in = new java.net.URL(URL_OF_IMAGE).openStream();
bitmap= BitmapFactory.decodeStream(in);
} catch (Exception e) {
}
return bitmap;
}
protected void onPostExecute(Bitmap result) {
loadedImage.setImageBitmap(result);
}
但请注意,您应该扩展 AsyncTask
,第一个参数应为 String
,最后一个参数为 Bitmap
,如
private class DowmloadImage extends AsyncTask<String, Void, Bitmap>
您可以使用网络图像视图代替图像视图。它肯定会让你的生活更轻松。
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/networkImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#000000"/>
这应该替换为所需 XML 文件中的图像视图。
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new LruBitmapCache());
}
return this.mImageLoader;
}
上面的 class 还创建了一个 ImageCache,它与普通的 volley 缓存一起工作,但只缓存请求的图像。
设置图像URL。
advImage.setImageUrl("Your Image URL", AppController.getInstance().getImageLoader());
相应地调用图像加载器函数。您也可以设置默认的占位符图像。
您可以编写自己的代码。但是使用库处理与库关联的所有样板代码。除非另有原因,我还建议您使用图书馆。以下是您在编写自己的代码时需要考虑的一些样板文件。
内存管理: 外部库负责确保图像不会占用您应用的所有可用内存。 Android 位图在处理时非常注重记忆,因此最好将这部分交给图书馆。
处理activity销毁:如果您在图像下载过程中旋转phone,它将重新创建activity 然后你将需要处理取消之前的请求并重新启动它们。
取消以前的请求: 图像库的编写使得不再可见的列表视图项目不会继续下载。假设你向下滚动。那么下载第一行中的图像就没有意义了。您应该取消此类下载并开始下载新图像。图片下载器库就是为处理这些问题而编写的。
缓存: 图像库使用内存缓存和磁盘缓存来存储下载的位图。因此,他们只会下载新图像,除非它们不可用。
从 UI 线程加载大型位图: 假设您的应用包含大型位图。为了将它们加载到您的视图中,您必须首先从磁盘加载它们。您需要编写代码,以便加载它们不会阻塞主线程 UI。
加载相关图像尺寸:您的应用程序可能运行具有高屏幕密度的新Android设备或旧设备屏幕密度低。根据您的目标设备,如果您的设备不支持这样的屏幕密度,您将不需要加载全分辨率图像。通常图书馆会为您处理,
这些只是要考虑的一些样板文件。因此,我强烈建议您在图像加载部分使用一个好的库,除非它非常需要!!!