此代码使用来自JSON的Web上的数据更新2 ListView,并且LazyAdapter将图像从URL转换并放在ListView上,在2.3上工作正常但在Android 4.0上不起作用。
这是代码
EventosActivity.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.eventos);
hojeLista = new ArrayList<HashMap<String, String>>();
proximosLista = new ArrayList<HashMap<String, String>>();
new LoadEventos().execute();
}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class LoadEventos extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(EventosActivity.this);
pDialog.setMessage("Dando uma olhada aqui, peraê...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All evento from url
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_hoje, "GET", params);
JSONObject json2 = jParser.makeHttpRequest(url_proximos, "GET", params);
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
int success2 = json2.getInt(TAG_SUCCESS);
if (success == 1) {
// evento found
// Getting Array of Products
evento = json.getJSONArray(TAG_EVENTO);
// looping through All Products
for (int i = 0; i < evento.length(); i++) {
JSONObject c = evento.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_ID);
String titulo = c.getString(TAG_TITULO);
String local_nome = c.getString(TAG_LOCAL_NOME);
String data = c.getString(TAG_DATA);
String imagem = c.getString(TAG_IMAGEM);
//if ("16".equals(TAG_CLASSIFICACAO)) { }
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_TITULO, titulo);
map.put(TAG_LOCAL_NOME, local_nome);
map.put(TAG_DATA, data);
map.put(TAG_IMAGEM, imagem);
// adding HashList to ArrayList
hojeLista.add(map);
}
}
if (success2 == 1) {
// evento found
// Getting Array of Products
evento = json2.getJSONArray(TAG_EVENTO);
// looping through All Products
for (int i = 0; i < evento.length(); i++) {
JSONObject c2 = evento.getJSONObject(i);
// Storing each json item in variable
String id = c2.getString(TAG_ID);
String titulo = c2.getString(TAG_TITULO);
String local_nome = c2.getString(TAG_LOCAL_NOME);
String data = c2.getString(TAG_DATA);
String imagem = c2.getString(TAG_IMAGEM);
//if ("16".equals(TAG_CLASSIFICACAO)) { }
// creating new HashMap
HashMap<String, String> map2 = new HashMap<String, String>();
// adding each child node to HashMap key => value
map2.put(TAG_ID, id);
map2.put(TAG_TITULO, titulo);
map2.put(TAG_LOCAL_NOME, local_nome);
map2.put(TAG_DATA, data);
map2.put(TAG_IMAGEM, imagem);
// adding HashList to ArrayList
proximosLista.add(map2);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all evento
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
ListView list = (ListView)findViewById(android.R.id.list);
ListView list2 = (ListView)findViewById(R.id.lvProximos);
ks.
LazyAdapter adapter=new LazyAdapter(EventosActivity.this, hojeLista);
list.setAdapter(adapter);
LazyAdapter adapter2=new LazyAdapter(EventosActivity.this, proximosLista);
list2.setAdapter(adapter2);
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String id2 = ((TextView) view.findViewById(R.id.id)).getText().toString();
Intent in = new Intent(getApplicationContext(), EventoDetalheActivity.class);
in.putExtra(TAG_ID, id2);
startActivityForResult(in, 100);
}
});
list2.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String id2 = ((TextView) view.findViewById(R.id.id)).getText().toString();
Intent in = new Intent(getApplicationContext(), EventoDetalheActivity.class);
in.putExtra(TAG_ID, id2);
startActivityForResult(in, 100);
}
});
}
});
}
}}
LazyAdapter.java
public class LazyAdapter extends BaseAdapter {
private Context activity;
private ArrayList<HashMap<String, String>> data;
private LayoutInflater inflater=null;
//public ImageLoader imageLoader;
private URL url;
private Bitmap bmp;
public LazyAdapter(Context a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.eventoitem, null);
TextView id = (TextView)vi.findViewById(R.id.id);
TextView titulo = (TextView)vi.findViewById(R.id.titulo);
TextView local_nome = (TextView)vi.findViewById(R.id.local_nome);
TextView data0 = (TextView)vi.findViewById(R.id.data);
ImageView im=(ImageView)vi.findViewById(R.id.imgImagem);
HashMap<String, String> evento = new HashMap<String, String>();
evento = data.get(position);
// Setting all values in listview
id.setText(evento.get("id"));
titulo.setText(evento.get("titulo"));
local_nome.setText(evento.get("local_nome"));
data0.setText(evento.get("data"));
try {
url = new URL(evento.get("imagem"));
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
im.setImageBitmap(bmp);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return vi;
}
}
谢谢你的帮助。
答案 0 :(得分:2)
问题在于你的getView方法,它在UI线程上运行但你已经调用了一些使用互联网的东西。这是有问题的电话:
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
im.setImageBitmap(bmp);
从特定版本的android(我记得蜂窝)开始,这是不允许的,因为互联网使用可能需要一段时间,你不应该让UI等待它完成。
你发现它是一件好事,因为它可能会导致ANR,因为互联网在没有任何崩溃的情况下工作得太慢。
解决这个问题的一种方法是对每个视图使用ViewHolder,它还包括一个asyncTask,用于加载图像并在完成后将其设置为相关的ImageView。如果viewHolder已经有一个任务,它应该被取消,因为它属于不再可见的东西。如果需要,还可以添加缓存机制。
一般情况下,如果您怀疑某个函数可以运行很长时间(比如超过1秒),您应该让它在后台运行(或尝试真正改进它)而不是让UI线程处理它。原因是你将得到一个非流动的应用程序,如果你的功能运行大约5秒左右,你也会得到一个ANR。
答案 1 :(得分:0)
当您尝试从主UI线程进行网络实现操作时,会发生NetworkOnMainThreadException。你应该在像asynctask这样的后台线程上做同样的事情。
在你的getview中,你正在下载一个位图。
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
im.setImageBitmap(bmp);
我同意android开发者。
您还应该使用viewholder来查看listview。 http://developer.android.com/training/improving-layouts/smooth-scrolling.html
http://www.youtube.com/watch?v=wDBM6wVEO70。该视频对Viewholder和listview有很好的解释。
我建议你使用 Universal Image Loader。
Lazy List是使用url从sdcard或fomr服务器延迟加载图像。这就像点播加载图片一样。
图像可以缓存到本地SD卡或手机存储卡中。网址被认为是关键。如果密钥存在于sdcard显示图像来自SD卡,则通过从服务器下载显示图像并将其缓存到您选择的位置。可以设置缓存限制。您还可以选择自己的位置来缓存图像。缓存也可以被清除。
而不是用户等待下载大图像,然后显示延迟列表按需加载图像。由于缓存了图像区域,您可以离线显示图像。
https://github.com/thest1/LazyList。懒惰列表
在你的getview中
imageLoader.DisplayImage(imageurl, imageview);
ImageLoader Display method
public void DisplayImage(String url, ImageView imageView) //url and imageview as parameters
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url); //get image from cache using url as key
if(bitmap!=null) //if image exists
imageView.setImageBitmap(bitmap); //dispaly iamge
else //downlaod image and dispaly. add to cache.
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
Lazy List的替代方案是Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader。它基于Lazy List(基于相同的原理)。但它有很多其他配置。我更喜欢使用通用图像加载器因为它为您提供了更多配置选项。如果下载失败,您可以显示错误图像。可以显示带圆角的图像。可以缓存在光盘或内存上。可压缩图像。
在自定义适配器构造函数
中 File cacheDir = StorageUtils.getOwnCacheDirectory(context, "your folder");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
在你的getView()
中 ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options
答案 2 :(得分:0)
出于显而易见的原因,不建议这样做,但您可以将其添加到您的班级中:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy);