在我的UI中,第一张图片总是随机的,起初我试图清理项目并从AVD中擦除个人数据,但这没有用。随机只有第一张图片,所有其他图片都正确显示。从活动开始几秒钟后,图片会多次更改。
请不要引用Android ocasionally downloads images from url的副本,因为它是不同的(并已解决)问题
public class ImageLoader {
MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
public ImageLoader(Context context){
fileCache=new FileCache(context);
executorService=Executors.newFixedThreadPool(5);
}
int stub_id = R.drawable.ic_launcher;
public void DisplayImage(String uurl, int loader, ImageView imageView)
{
String url = uurl.replaceAll(" ", "%20");
url = url.replaceAll("\n", "%20");
stub_id = loader;
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
{
queuePhoto(url, imageView);
imageView.setImageResource(loader);
}
}
private void queuePhoto(String url, ImageView imageView)
{
PhotoToLoad p=new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
return downloadBitmap(url);
//from web
/*try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}*/
}
Bitmap downloadBitmap(String url){
Bitmap bmp = null;
URL url_1 = null;
try {
url_1 = new URL(url);
bmp = BitmapFactory.decodeStream(url_1.openConnection().getInputStream());
} catch (Exception e) {
Log.v("Error while downloading bitmap from url", e.getMessage());
}
return bmp;
}
//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;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad=photoToLoad;
}
public void run() {
if(imageViewReused(photoToLoad))
return;
Bitmap bmp=getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
if(imageViewReused(photoToLoad))
return;
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
boolean imageViewReused(PhotoToLoad photoToLoad){
String tag=imageViews.get(photoToLoad.imageView);
if(tag==null || !tag.equals(photoToLoad.url))
return true;
return false;
}
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
public void run()
{
if(imageViewReused(photoToLoad))
return;
if(bitmap!=null)
photoToLoad.imageView.setImageBitmap(bitmap);
else
photoToLoad.imageView.setImageResource(stub_id);
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
}
filecash
public class FileCache {
private File cacheDir;
public FileCache(Context context){
//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(),"TempImages");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
public File getFile(String url){
String filename=String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
return f;
}
public void clear(){
File[] files=cacheDir.listFiles();
if(files==null)
return;
for(File f:files)
f.delete();
}
}
记忆现金
public class MemoryCache {
private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());
public Bitmap get(String id){
if(!cache.containsKey(id))
return null;
SoftReference<Bitmap> ref=cache.get(id);
return ref.get();
}
public void put(String id, Bitmap bitmap){
cache.put(id, new SoftReference<Bitmap>(bitmap));
}
public void clear() {
cache.clear();
}
}
刺
public class Utils {
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){}
}
}
适配器
public class CandidateAdapter extends BaseAdapter{
Context ctx;
LayoutInflater lInflater;
ArrayList<Candidate> objects;
CandidateAdapter(Context context, ArrayList<Candidate> candidates) {
ctx = context;
objects = candidates;
lInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return objects.size();
}
public Object getItem(int position) {
return objects.get(position);
}
public long getItemId(int position) {
return position;
}
Candidate getCandidate(int position) {
return ((Candidate) getItem(position));
}
public View getView(int position, View convertView, ViewGroup parent) {
// используем созданные, но не используемые view
View view = convertView;
if (view == null) {
view = lInflater.inflate(R.layout.inbox_list_item, parent, false);
}
Candidate p = getCandidate(position);
((TextView) view.findViewById(R.id.from)).setText(p.get_name());
((TextView) view.findViewById(R.id.subject)).setText(p.get_office());
((RatingBar) view.findViewById(R.id.rateindicator)).setRating(p.get_ranking());
int loader = R.drawable.loader;
ImageView image = (ImageView) view.findViewById(R.id.photo);
String image_url = p.get_photograph();
ImageLoader imgLoader = new ImageLoader(ctx);
imgLoader.DisplayImage(image_url, loader, image);
return view;
}
}
活性
public class InboxActivity extends ListActivity {
List<Candidate> candidates;
private DatabaseHandler db;
public void onDestroy(){
if (db != null)
db.close();
super.onDestroy();
//db.close();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inbox_list);
db = new DatabaseHandler(this);
candidates = db.getAllCandidates(1);
db.close();
CandidateAdapter adapter = new CandidateAdapter(this,(ArrayList) candidates);
ListView lvMain = getListView();
//String numofrows = "" + candidates.size();
//Log.d("Number of candidates", numofrows);
lvMain.setAdapter(adapter);
lvMain.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.from)).getText().toString();
Log.d("Name ", name);
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra("name", name);
Log.d("Starting activity ", "Yeah ");
startActivity(in);
}
});
}
}
logcat警告
12-16 08:35:33.525:W / Zygote(33):预装的可绘制资源#0x1080093(res / drawable-hdpi / sym_def_app_icon.png)因配置而异!!
有人可以帮我解决这个问题吗?
getall候选函数
public List<Candidate> getAllCandidates(int status) {
List<Candidate> candidateList = new ArrayList<Candidate>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_CANDIDATES;
db = this.getReadableDatabase();
cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Candidate candidate = new Candidate();
if (status == Integer.parseInt(cursor.getString(5))) {
candidate.set_name(cursor.getString(0));
candidate.set_office(cursor.getString(1));
candidate.set_photograph(cursor.getString(2));
candidate.set_promises(cursor.getString(3));
candidate.set_statment(cursor.getString(4));
candidate.set_active(Integer.parseInt(cursor.getString(5)));
candidate.set_ranking(Integer.parseInt(cursor.getString(6)));
// Adding candidate to list
candidateList.add(candidate);
}
} while (cursor.moveToNext());
}
// return candidate list
db.close();
cursor.close();
return candidateList;
}
答案 0 :(得分:0)
您的imageView可能会被列表视图回收。您的问题可能是传递给ImageLoader的图像的陈旧参考。
您可以在调用DisplayImage之前检查imageView的实例,然后在加载之后验证这一点。
ImageLoader imgLoader = new ImageLoader(ctx);
imgLoader.DisplayImage(image_url, loader, image);
您可能需要考虑使用视图模式来保存ImageLoader,而不是每次都创建一个新的,这也可能有所帮助。
类似
ImageLoader imgLoader = (ImageLoader) view.getTag()
if(imgLoader == null){
imgLoader = new ImageLoader(ctx);
view.setTag(imgLoader);
}
这只是在捅它。很难知道没有运行它,但希望它有帮助:) 祝你好运