Вопрос

This code update a 2 ListView with data from JSON on Web and LazyAdapter convert the images from URL and put on ListView, works fine on 2.3 but on the Android 4.0 doesn't work.

This is the codes

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;
}

}

Thanks for Help me.

Это было полезно?

Решение 2

NetworkOnMainThreadException occurs when your trying to make a network realted operation from the main UI thread. You should be doing the same on background thread like asynctask.

In your getview your are downlaoding a bitmap.

bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
   im.setImageBitmap(bmp);

I agree with android developer.

You should also use viewholder fro listview. http://developer.android.com/training/improving-layouts/smooth-scrolling.html.

http://www.youtube.com/watch?v=wDBM6wVEO70. The video has a good explanation on Viewholder and listview.

I would suggest you to use Universal Image Loader.

Lazy List is lazy loading of images from sdcard or fomr server using urls. It is like on demand loading images.

Images can be cached to local sd card or phone mmeory. Url is considered the key. If the key is present in sdcard display images from sd card else display image by downloading from server and cache the same to location of your choice. The cache limit can set. You can also choose your own location to cache images. Cache can also be cleared.

Instead of user waiting to download large images and then displaying lazy list loads images on demand. Since images area cached you can display images offline.

https://github.com/thest1/LazyList. Lazy List

In your 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);
 }
 }

An alternative to Lazy List is Universal Image Loader

https://github.com/nostra13/Android-Universal-Image-Loader. It is based on Lazy List(works on same principle). But it has lot of other configurations. I would prefer to use Universal Image Loader coz it gives you more configuration options. You can display a error image if downlaod failed. Can display images with rounded corners. Can cache on disc or memory. Can compress image.

In your custom adapter constructor

 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();

In your getView()

 ImageView image=(ImageView)vi.findViewById(R.id.imageview); 
 imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options

Другие советы

The problem is on your getView method, which runs on the UI thread yet you've called something that uses the internet. here's the problematic call:

bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
       im.setImageBitmap(bmp);

As of a certain version of android (honeycomb as far as i remember), this is not allowed as internet usage can take a while and you shouldn't let the UI wait for it to finish.

It's a good thing you've found it, as it could cause ANRs in case the internet is too slow on devices that it worked without any crashes.

One way to solve it is to use ViewHolder for each view, which will also include an asyncTask for loading the image and set it to the relevant ImageView upon completion. if the viewHolder already has a task, it should be cancelled as it was belong to something that is no longer visible. You can also add cache mechanism if you want to.

In general, if you suspect that a certain function could run for a long time (say, more than 1 second) , you should make it run in the background (or try to really improve it) instead of letting the UI thread handle it. The reason is that you will get a non-fluid app, and if you have the function run for about 5 seconds or so, you will also get an ANR.

It is not recommended, for obvious reasons, but you can add this to your class:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build() 
StrictMode.setThreadPolicy(policy); 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top