- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个自定义的 ListView 适配器,它实现了一个 ImageThreadLoader 类。不幸的是,该类没有启用缓存选项 - 从 Web 下载图像并将它们保存为缓存。
然后我找到了这个 LazyList或 here非常有用,它的行为与我的 ImageThreadLoader 类完全相同,但它能够将图像保存为缓存。所以,我想将它的 ImageLoader 类实现到我当前的自定义 ListView 适配器。
不幸的是,我的代码结构和 Lazylist 的代码结构完全不同,导致我的尝试出现一些冲突。例如,LazyList 使用字符串数组作为图像 URL,而另一方面,我使用 JSON 作为图像 URL 的来源。
这就是为什么我在这里需要帮助来使我的 ListView 适配器适应这个 ImageLoader 类。
代码如下:
我想在我的自定义 ListView 适配器中实现的 ImageLoader 类:
public class ImageLoader {
//the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
private File cacheDir;
public ImageLoader(Context context){
//Make the background thead low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"Android/data/LazyList");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
final int stub_id=R.drawable.stub;
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
if(cache.containsKey(url))
imageView.setImageBitmap(cache.get(url));
else
{
queuePhoto(url, activity, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
private Bitmap getBitmap(String url)
{
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
File f=new File(cacheDir, filename);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
InputStream is=new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
PhotosQueue photosQueue=new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image)
photosToLoad.remove(j);
else
++j;
}
}
}
class PhotosLoader extends Thread {
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag=photoToLoad.imageView.getTag();
if(tag!=null && ((String)tag).equals(photoToLoad.url)){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
PhotosLoader photoLoaderThread=new PhotosLoader();
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
}
}
public void clearCache() {
//clear memory cache
cache.clear();
//clear SD cache
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
}
来自 LazyList 项目的自定义 ListView 适配器:
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private String[] data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, String[] d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder{
public TextView text;
public ImageView image;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.item, null);
holder=new ViewHolder();
holder.text=(TextView)vi.findViewById(R.id.text);;
holder.image=(ImageView)vi.findViewById(R.id.image);
vi.setTag(holder);
}
else
holder=(ViewHolder)vi.getTag();
holder.text.setText("item "+position);
holder.image.setTag(data[position]);
imageLoader.DisplayImage(data[position], activity, holder.image);
return vi;
}
}
这是我的自定义 ListView 适配器:ProjectAdapter 类
public class ProjectAdapter extends ArrayAdapter<Project> {
int resource;
String response;
Context context;
private final static String TAG = "MediaItemAdapter";
private ImageThreadLoader imageLoader = new ImageThreadLoader();
//Initialize adapter
public ProjectAdapter(Context context, int resource, List<Project> items) {
super(context, resource, items);
this.resource=resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
TextView textTitle;
final ImageView image;
Project pro = getItem(position);
LinearLayout projectView;
//Inflate the view
if(convertView==null)
{
projectView = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater vi;
vi = (LayoutInflater)getContext().getSystemService(inflater);
vi.inflate(resource, projectView, true);
}
else
{
projectView = (LinearLayout) convertView;
}
try {
textTitle = (TextView)projectView.findViewById(R.id.txt_title);
image = (ImageView)projectView.findViewById(R.id.image);
} catch( ClassCastException e ) {
Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
throw e;
}
Bitmap cachedImage = null;
try {
cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() {
public void imageLoaded(Bitmap imageBitmap) {
image.setImageBitmap(imageBitmap);
notifyDataSetChanged(); }
});
} catch (MalformedURLException e) {
Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
}
textTitle.setText(pro.project_title);
if( cachedImage != null ) {
image.setImageBitmap(cachedImage);
}
return projectView;
}
}
非常感谢!!
编辑
更新:项目列表 Activity
public class ProjectsList extends Activity {
/** Called when the activity is first created. */
//ListView that will hold our items references back to main.xml
ListView lstTest;
//Array Adapter that will hold our ArrayList and display the items on the ListView
ProjectAdapter arrayAdapter;
ProgressDialog dialog;
//List that will host our items and allow us to modify that array adapter
ArrayList<Project> prjcts=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.projects_list);
//Initialize ListView
lstTest= (ListView)findViewById(R.id.lstText);
//Initialize our ArrayList
prjcts = new ArrayList<Project>();
//Initialize our array adapter notice how it references the listitems.xml layout
arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);
//Set the above adapter as the adapter of choice for our list
lstTest.setAdapter(arrayAdapter);
if (isOnline())
{
//Instantiate the Web Service Class with he URL of the web service not that you must pass
//WebService webService = new WebService("http://notalentrocks.com/myplaceapp/projects.json");
WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
//Pass the parameters if needed , if not then pass dummy one as follows
Map<String, String> params = new HashMap<String, String>();
params.put("var", "");
//Get JSON response from server the "" are where the method name would normally go if needed example
// webService.webGet("getMoreAllerts", params);
String response = webService.webGet("", params);
try
{
dialog = ProgressDialog.show(ProjectsList.this, "", "Fetching Projects...", true);
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
dialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
}
});
//Parse Response into our object
Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
//JSON expects an list so can't use our ArrayList from the lstart
List<Project> lst= new Gson().fromJson(response, collectionType);
//Now that we have that list lets add it to the ArrayList which will hold our items.
for(Project l : lst)
{
prjcts.add(l);
ConstantData.projectsList.add(l);
}
//Since we've modified the arrayList we now need to notify the adapter that
//its data has changed so that it updates the UI
arrayAdapter.notifyDataSetChanged();
dialog.dismiss();
}
catch(Exception e)
{
Log.d("Error: ", e.getMessage());
}
}
lstTest.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
care.putExtra("spendino.de.ProjectDetail.position",position);
startActivity(care);
}
});
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
} else {
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setTitle("spendino Helfomat");
alertbox.setMessage ("Please check your internet connection");
alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//Main.this.finish();
}
});
alertbox.show();
return false;
}
}
}
已更新这是我的堆栈跟踪:
05-12 11:36:52.670: ERROR/AndroidRuntime(299): Caused by: java.lang.NullPointerException
05-12 11:36:52.670: ERROR/AndroidRuntime(299): at android.content.ContextWrapper.getCacheDir(ContextWrapper.java:183)
05-12 11:38:29.386: ERROR/AndroidRuntime(324): at spendino.de.ImageLoader.<init>(ImageLoader.java:41)
05-12 11:36:52.670: ERROR/AndroidRuntime(299): at spendino.de.Main.<init>(Main.java:56)
ImageLoader 41 是:cacheDir=context.getCacheDir();
Main 56 是:private ImageLoaderCache imageLoader = new ImageLoaderCache(Main.this);
主.java
公共(public)类 Main 扩展 Activity { /** 在第一次创建 Activity 时调用。 */
ArrayList<Project> prjcts=null;
private final static String TAG = "MediaItemAdapter";
ImageLoader imageLoader;
private Activity activity;
ImageView image1;
ImageView image2;
ImageView image3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (isOnline())
{
prjcts = new ArrayList<Project>();
WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
Map<String, String> params = new HashMap<String, String>();
params.put("var", "");
String response = webService.webGet("", params);
imageLoader = new ImageLoader(Main.this);
try
{
Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
List<Project> lst= new Gson().fromJson(response, collectionType);
for(Project l : lst)
{
prjcts.add(l);
ConstantData.projectsList.add(l);
}
}
catch(Exception e)
{
Log.d("Error: ", e.getMessage());
}
try {
image1 = (ImageView)findViewById(R.id.top1);
image2 = (ImageView)findViewById(R.id.top2);
image3 = (ImageView)findViewById(R.id.top3);
} catch( ClassCastException e ) {
Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
throw e;
}
//randomize the index of image entry
int max = prjcts.size();
List<Integer> indices = new ArrayList<Integer>(max);
for(int c = 1; c < max; ++c)
{
indices.add(c);
}
Random r = new Random();
int arrIndex = r.nextInt(indices.size());
int randomIndex1 = indices.get(arrIndex);
indices.remove(arrIndex);
int arrIndex2 = r.nextInt(indices.size());
int randomIndex2 = indices.get(arrIndex2);
indices.remove(arrIndex2);
int arrIndex3 = r.nextInt(indices.size());
int randomIndex3 = indices.get(arrIndex3);
indices.remove(arrIndex3);
imageLazy(image1, prjcts.get(randomIndex1));
imageLazy(image2, prjcts.get(randomIndex2));
imageLazy(image3, prjcts.get(randomIndex3));
image1.setOnClickListener(new RandomClickListener(randomIndex1));
image2.setOnClickListener(new RandomClickListener(randomIndex2));
image3.setOnClickListener(new RandomClickListener(randomIndex3));
}
final Button project = (Button) findViewById(R.id.btn_projectslist);
final Button infos = (Button) findViewById(R.id.btn_infos);
final Button contact = (Button) findViewById(R.id.btn_contact);
project.setOnClickListener(project_listener);
infos.setOnClickListener(infos_listener);
contact.setOnClickListener(contact_listener);
}
/*
* isOnline - Check if there is a NetworkConnection
* @return boolean
*/
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
} else {
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setTitle("spendino Helfomat");
alertbox.setMessage ("Bitte überprüfen Sie Ihre Internetverbindung");
alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Main.this.finish();
}
});
alertbox.show();
return false;
}
}
public static class ViewHolder{
public ImageView image;
}
public void imageLazy(final ImageView image,Project pro)
{
imageLoadery.displayImage(pro.smallImageUrl, activity, image);
}
public void setImage(Bitmap cachedImage, final ImageView image, Project pro)
{
try {
cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener()
{
public void imageLoaded(Bitmap imageBitmap)
{
image.setImageBitmap(imageBitmap);
}
});
} catch (MalformedURLException e) {
Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
}
if( cachedImage != null ) {
image.setImageBitmap(cachedImage);
}
}
public class RandomClickListener implements View.OnClickListener
{
private final int randomIndex;
public RandomClickListener(final int randomIndex)
{
this.randomIndex = randomIndex;
}
@Override
public void onClick(View v)
{
Intent top = new Intent(Main.this, ProjectDetail.class);
top.putExtra("spendino.de.ProjectDetail.position", randomIndex);
startActivity(top);
}
}
堆栈跟踪:
05-12 13:48:12.606: ERROR/AndroidRuntime(433): at spendino.de.ImageLoaderCache$PhotosLoader.run(ImageLoaderCache.java:244)
最佳答案
似乎您没有在适配器中使用任何 View 持有者
我已经对你的类(class)进行了修改。希望它对你有用,没有任何困难
ImageThreadLoader 类
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
public class ImageThreadLoader {
//the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
/** The cache. */
private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();
/** The cache dir. */
private File cacheDir;
/**
* Instantiates a new image loader.
*
* @param context the context
*/
public ImageThreadLoader(Context context){
//Make the background thead low priority. This way it will not affect the UI performance
photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"cache_dir_img");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
//This is used for a stub when the user can not see the actual image..
//this images will be seen
final int stub_id =R.drawable.sample_image;
/**
* Display image.
*
* @param url the url
* @param activity the activity
* @param imageView the image view
*/
public void displayImage(String url, Activity activity, ImageView imageView)
{
if(cache.containsKey(url))
imageView.setImageBitmap(cache.get(url));
else
{
queuePhoto(url, activity, imageView);
imageView.setImageResource(stub_id);
}
}
/**
* Queue photo.
*
* @param url the url
* @param activity the activity
* @param imageView the image view
*/
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
//This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p=new PhotoToLoad(url, imageView);
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
//start thread if it's not started yet
if(photoLoaderThread.getState()==Thread.State.NEW)
photoLoaderThread.start();
}
/**
* Gets the bitmap.
*
* @param url the url
* @return the bitmap
*/
private Bitmap getBitmap(String url)
{
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
File f=new File(cacheDir, filename);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
InputStream is=new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
copyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
/**
* Decode file.
*
* @param f the f
* @return the bitmap
*/
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale++;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
/**
* The Class PhotoToLoad.
*/
private class PhotoToLoad
{
/** The url. */
public String url;
/** The image view. */
public ImageView imageView;
/**
* Instantiates a new photo to load.
*
* @param u the u
* @param i the i
*/
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
/** The photos queue. */
PhotosQueue photosQueue=new PhotosQueue();
/**
* Stop thread.
*/
public void stopThread()
{
photoLoaderThread.interrupt();
}
//stores list of photos to download
/**
* The Class PhotosQueue.
*/
class PhotosQueue
{
/** The photos to load. */
private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();
//removes all instances of this ImageView
/**
* Clean.
*
* @param image the image
*/
public void Clean(ImageView image)
{
for(int j=0 ;j<photosToLoad.size();){
if(photosToLoad.get(j).imageView==image)
photosToLoad.remove(j);
else
++j;
}
}
}
/**
* The Class PhotosLoader.
*/
class PhotosLoader extends Thread {
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
public void run() {
try {
while(true)
{
//thread waits until there are any images to load in the queue
if(photosQueue.photosToLoad.size()==0)
synchronized(photosQueue.photosToLoad){
photosQueue.photosToLoad.wait();
}
if(photosQueue.photosToLoad.size()!=0)
{
PhotoToLoad photoToLoad;
synchronized(photosQueue.photosToLoad){
photoToLoad=photosQueue.photosToLoad.pop();
}
Bitmap bmp=getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
if(((String)photoToLoad.imageView.getTag()).equals(photoToLoad.url)){
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if(Thread.interrupted())
break;
}
} catch (InterruptedException e) {
//allow thread to exit
}
}
}
/** The photo loader thread. */
PhotosLoader photoLoaderThread=new PhotosLoader();
//Used to display bitmap in the UI thread
/**
* The Class BitmapDisplayer.
*/
class BitmapDisplayer implements Runnable
{
/** The bitmap. */
Bitmap bitmap;
/** The image view. */
ImageView imageView;
/**
* Instantiates a new bitmap displayer.
*
* @param b the b
* @param i the i
*/
public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run()
{
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
}
}
/**
* Clear cache.
*/
public void clearCache() {
//clear memory cache
cache.clear();
//clear SD cache
File[] files=cacheDir.listFiles();
for(File f:files)
f.delete();
}
public static void copyStream(InputStream is, OutputStream os) {
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
}
现在你的ProjectAdapter类
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ProjectAdapter extends ArrayAdapter<Project> {
int resource;
String response;
Context context;
List<Project> items;
private ImageThreadLoader imageLoader;
LayoutInflater mInflater;
Activity activity;
// Initialize adapter
public ProjectAdapter(Context context, int resource, List<Project> items,
Activity activity) {
super(context, resource, items);
this.resource = resource;
imageLoader = new ImageThreadLoader(context);
this.items = items;
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.activity = activity;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
// Inflate the view
if (convertView == null) {
convertView = mInflater.inflate(resource, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.textTitle = (TextView) convertView
.findViewById(R.id.txt_title);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Project project = items.get(position);
holder.textTitle.setText(project.project_title);
String imageurl = project.smallImageUrl;
holder.image.setTag(imageurl);
imageLoader.displayImage(imageurl, activity, holder.image);
return convertView;
}
static class ViewHolder {
TextView textTitle;
ImageView image;
}
最后,当您在获取网络数据后在 ListView
中设置适配器时,请使用此
your_listview.setAdapter(your_ProjectAdapter_instance );
your_ProjectAdapter_instance .notifyDataSetChanged();
关于Android:帮助使用 ImageLoader 类 (LazyList) 适配 ListView 适配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5867894/
ios10 适配-xcode8 问题解决: ios开发者,系统版本的更新,必定要跟着更新,不然有些功能不知道,开发的时候对可以体验,大打折扣了。 前段时间升级了xcode8,整体来说对oc的影响不
问题 TableView 的 setTableMenuButtonVisible 提供了一种机制来更改表列的可见性。然而,该功能还有很多不足之处: 菜单应保持打开状态。我有 e。 G。 15个表格列,
我正在开发一个使用 MapKit 的应用程序。鉴于 2012 年 6 月 11 日的 Apple 公告,我是否必须使用新的 API 完全重写它才能跟上这些变化? 最佳答案 iOS 6 仍处于 NDA
最近看了许多iphone x适配的文章,发现很少有介绍safearea的,就来随便写写 现在对于iphone x的适配,有一种常见的做法是给导航栏或tabbar增加一个固定的距离,比如顶部增加44
我正在使用 Big Nerd Ranch's recyclerview-multiselect库为我的 RecyclerView 的 CardViews 提供多选功能。我已经解决了大部分应用程序特定的
The Table with bad text-alignment 在图片中,您会看到文本对齐不正确的表格。 tbody 的元素不适合 thead 的元素。表头固定很重要,这样即使向下滚动也能看到。
我将尝试设置我的应用程序,以便它可以使用 Apple map 或 Google map ,所以我想我会有这样的东西: class AppleMap: MKMapView, MyMapProtocol
我已经在网站上工作了大约一个星期,我们需要包含一些非常规字体。没问题,我会在 CSS 中使用 @font-face{},它就像一个魅力。 . .除非你的名字是 Internet Explorer。 由
我遇到了一个问题,csv 文件中的字符显示为带有 ?在中间。 我已经编写了解析 csv 的代码,但我不明白为什么字符串不能正确读取 unicode 字符。这可能与我的实现有关: StreamReade
试图在底部模仿当前的谷歌地图栏。我失败了那么多,也尝试了那么多; CollapsingToolbar、BottomSheet、自定义库。 我想要的:当 BottomSheet 滑动时,让 map Vi
我有 5000 行 CSS 用于 Firefox、Opera,有时还有 IE 8。毕竟,account 告诉我,它必须在 IE 7 下正常工作。我该怎么做,而不重写 40% 的代码? 最佳答案 在
我使用 Glide 和 CircleTransform 将圆形图像放入此 ImageView。 ImageView 具有 wrap_content 属性,但是 ImageView 不适合 Circle
为什么 Apache Hive 需要 Apache Thrift?在 Thrift 的网站上,它说它可以用多种语言编译,但我不明白它适合哪里以及为什么 Hive 需要它。谢谢 最佳答案 引用 from
我使用此命令在 m4v 中转换了一些 YUV 视频,请注意我使用的是 CIF 格式的视频: ffmpeg -s cif -r 30 -i video.yuv -vcodec mpeg4 -g 30 -
我已从教程中获取代码并尝试对其进行修改以包括双向性和 GRU 的任意数量的层。 链接到使用单向、单层 GRU 的教程: https://pytorch.org/tutorials/intermedia
在使用 C++ 11 进行测试期间,我使用了以下结构: std::for_each( coll.begin(), coll.end(), [ &obj, expRes ]( const val
假设我有一个带有 std::pair 的 STL 容器。有什么方法可以使用 boost 为 STL 算法 lambda 调整对的秒数? std::vector> vec; const auto Pre
我有一个自定义的 ListView 适配器,它实现了一个 ImageThreadLoader 类。不幸的是,该类没有启用缓存选项 - 从 Web 下载图像并将它们保存为缓存。 然后我找到了这个 Laz
我有一个关于在 CSS 中使用 PHP 的一般性问题。我现在正在研究 Wordpress 主题,并希望尽可能地定制它。因此,我将我想通过 PHP 更改的 CSS 属性发送到一个为我更改它们的 JS 文
我安装了包 react-treebeard https://react.rocks/example/react-treebeard 允许我为我的 React TS 网站提供一个开箱即用的树控件,它允许
我是一名优秀的程序员,十分优秀!