2013-03-26 2 views
-2

이 코드는 ListView를 웹에서 JSON의 데이터로 업데이트하고 LazyAdapter는 URL에서 이미지를 변환하여 ListView에 저장하고 2.3에서 제대로 작동하지만 Android 4.0에서는 작동하지 않습니다. 안드로이드 NetworkOnMainThreadException - 4.0 ListView JSON 및 LazyAdapter

는 코드

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

    } 

}} 

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

LazyAdapter.java

} 나에게 도움을

감사합니다.

+4

왜 onPostExecute()에서 runOnUiThread()를 작성하는지. 이 메소드는 이미 UI Thread에서 실행된다. [AsyncTask 's reference] (http://developer.android.com/reference/android/os/AsyncTask.html)를 읽어야합니다. – Sajmon

+0

이 질문은 여러 번 묻습니다'NetworkOnMainThreadExceptoin' 여기에 질문을 게시하기 전에 먼저 검색해야합니다. –

+0

검색이지만 내 질문에 대한 답장을 찾을 수 없습니다. –

답변

0

NetworkOnMainThreadException은 기본 UI 스레드에서 네트워크를 realted 조작하려고 할 때 발생합니다. asynctask와 같은 백그라운드 스레드에서 동일한 작업을 수행해야합니다.

getview에서 비트 맵을 다운로드하고 있습니다.

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

나는 안드로이드 개발자에 동의합니다.

또한 listholder listview를 사용해야합니다. http://developer.android.com/training/improving-layouts/smooth-scrolling.html.

http://www.youtube.com/watch?v=wDBM6wVEO70. 비디오에는 뷰 소유자 및 목록보기에 대한 설명이 있습니다.

유니버설 이미지 로더를 사용하는 것이 좋습니다.

지연 목록은 URL을 사용하여 sdcard 또는 fomr 서버에서 이미지를 지연로드하는 것입니다. 그것은 이미지를 로딩하는 것과 같다.

이미지는 로컬 sd 카드 또는 휴대 전화 mmeory에 캐시 할 수 있습니다. URL이 키로 간주됩니다.키가 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); 
} 
} 

게으른 목록에 대한 대안에 게으른 목록

유니버설 이미지 로더

https://github.com/nostra13/Android-Universal-Image-Loader입니다. Lazy List (동일한 원칙에 따라 작동)를 기반으로합니다. 그러나 다른 많은 설정이 있습니다. 유니버설 이미지 로더을 사용하면 더 많은 구성 옵션을 제공합니다. 다운로드가 실패하면 오류 이미지를 표시 할 수 있습니다. 모서리가 둥근 이미지를 표시 할 수 있습니다. 디스크 또는 메모리에 캐시 할 수 있습니다. 이미지를 압축 할 수 있습니다. 당신의 getView()에서 사용자 정의 어댑터 생성자

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

에서

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

문제점은 인터넷을 사용하는 무언가를 호출했지만 아직 UI ​​스레드에서 실행되는 getView 메소드에 있습니다. 여기에 문제가있는 전화입니다 : 안드로이드의 특정 버전 (지금까지 내가 기억하는 벌집)의로

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

, 이것은 시간이 걸릴 수 있습니다 인터넷 사용으로 허용되지 않습니다 당신은 그것을 위해 UI 대기 못하게한다 끝내기 위해.

인터넷이 너무 느려서 작동하지 않는 기기에서 인터넷이 느려질 경우를 대비해 ANR이 발생할 수 있으므로 찾기가 쉽습니다.

해결 방법 중 하나는 각보기에 대해 ViewHolder를 사용하는 것입니다. 이미지를로드하고 완료시 관련 ImageView에 설정하기위한 asyncTask도 포함됩니다. viewHolder에 이미 작업이있는 경우 더 이상 보이지 않는 항목에 속한 것처럼 취소해야합니다. 원하는 경우 캐시 메커니즘을 추가 할 수도 있습니다.

일반적으로 특정 기능이 장시간 (예 : 1 초 이상) 실행될 수 있다고 생각되면 UI를 실행하는 대신 백그라운드에서 실행하도록 설정하거나 (실제로는 개선을 시도해야합니다) 스레드가 처리합니다. 그 이유는 유동적이지 않은 앱을 얻게 될 것이고 약 5 초 정도 기능을 실행하게되면 ANR도 얻을 수 있기 때문입니다.

+0

예, Honeycomb : http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html – kabuko

0

그것은 분명한 이유를 들어, 사용하지 않는 것이 좋습니다,하지만 당신은 당신의 클래스에이를 추가 할 수 있습니다

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build() 
StrictMode.setThreadPolicy(policy); 
관련 문제