2013-07-01 3 views
0

У меня есть Listview с несколькими элементами, в каждом элементе есть 2 кнопки. То, что я хочу сделать, - это когда я нажимаю кнопку, он отправляет некоторые данные на сервер через HttpPost. Я поместил Thread внутри моего Adapter.getView(), но он не работает, потому что адаптер является aleady в Async Thread. У вас есть идея о том, как я могу заставить его работать?HttpPost внутри getView от адаптера

Мой ListView:

// ... OnCreate ListView ... 
// ... new ListAppTask().execute(); 
// ... 
public class ListAppTask extends AsyncTask<Void, Void, List<ProductExtended>> { 

    protected List<ProductExtended> doInBackground(Void... args) { 
     Product product = new Product(); 
     List<ProductExtended> products = product.getLastProducts(getApplicationContext()); 

     return products; 
    } 

    protected void onPostExecute(List<ProductExtended> result) { 
     data.addAll(result); 
     adapter.notifyDataSetChanged(); 
     if (progressDialog != null) { 
      progressDialog.dismiss(); 
      progressDialog = null; 
     } 
    } 
} 

Мой адаптер:

public class PackageAdapter extends BaseAdapter { 

     private List<ProductExtended> data; 
     private Context context; 

     public PackageAdapter(Context context, List<ProductExtended> data) { 
      this.context = context; 
      this.data = data; 
     } 

     @Override 
     public int getCount() { 
      return data.size(); 
     } 

     @Override 
     public ProductExtended getItem(int position) { 
      return data.get(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      return position; 
     } 

     @Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
      final ProductExtended item = getItem(position); 
      ViewHolder holder; 
      if (convertView == null) { 
       LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       convertView = li.inflate(R.layout.package_row, parent, false); 
       holder = new ViewHolder(); 
       holder.btnBa = (LinearLayout) convertView.findViewById(R.id.idBonneaffaire); 
       holder.btnJl = (LinearLayout) convertView.findViewById(R.id.idJelai); 
       convertView.setTag(holder); 
      } else { 
       holder = (ViewHolder) convertView.getTag(); 
      } 


      holder.btnBa.setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 

         new Thread() { 

          @Override 
          public void run() { 
           // ---------------- PROBLEM HERE ------------------- 
           HttpClient httpclient = new DefaultHttpClient(); 
           HttpPost httppost = new HttpPost("My URL"); 
           // Execute HTTP Post Request 
           try { 
            HttpResponse response = httpclient.execute(httppost); 
            String reponse = EntityUtils.toString(response.getEntity()); 

           } catch (UnknownHostException e) { 
           } catch (HttpHostConnectException e) { 
           } catch (ClientProtocolException e) { 
           } catch (IOException e) { 
           } 
          } 
         }.start(); 
       } 
      }); 

      // Same for the second LinearLayout considered as Button 



      return convertView; 
     } 

     static class ViewHolder { 
      LinearLayout btnBa; 
      LinearLayout btnJl; 
     } 

И ошибка отображаемая:

Only the original thread that created a view hierarchy can touch its views. adapter 

Спасибо годов, Акрам

+0

Как обычно, люди получат фрагмент кода и ваш точный код ошибки («не работает =?»). Кроме того, вы не могли бы уточнить, что вы имеете в виду, что ваш адаптер находится в потоке Async - строго говоря, он должен обновлять только поток UI. Благодарю. – Tom

ответ

2

Эта ошибка в основном описывают, что вы пытаетесь обновить пользовательский интерфейс из другого потока, кроме основного. Это произойдет, если по какой-либо причине вы попытаетесь прикоснуться к вашему представлению в методах «Выполнить» ваших потоков, собранных вашим onClickListener. В вашем примере это не видно, но можете ли вы проверить, что вы делаете там, где вы указали «// То же самое для второго LinearLayout, которое рассматривается как кнопка»?

Чтобы предотвратить это исключение, вы можете использовать android.os.Handler для запуска Runnable в основном потоке всякий раз, когда вам нужно обновить интерфейс.

Например:

Handler mHandler = new Handler(); 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    final ViewHolder holder; 
    if(convertView == null){ 
     convertView = mInflater.inflate(R.layout.item_simple_row, parent, false); 
     holder = new ViewHolder(); 
     holder.textView = (TextView) convertView.findViewById(R.id.txt); 
     holder.button = (Button) convertView.findViewById(R.id.btn); 
     convertView.setTag(holder); 
    }else{ 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    final String url = getItemAtPosition(position); 
    holder.textView.setText(url); 
    holder.button.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      final Thread worker = new Thread(new Runnable(){ 

       @Override 
       public void run() 
       { 
//WATCH OUT IF YOU TOUCH YOUR VIEW HERE WITHOUT USING A HANDLER YOU MAY GET THE ERROR YOUR ARE TALKING ABOUT 

        HttpGet request = new HttpGet(url); 
        DefaultHttpClient httpClient = new DefaultHttpClient(); 
        try { 
         final HttpResponse response = httpClient.execute(request); 

         mHandler.post(new Runnable() { 

          @Override 
          public void run() { 
//UPDATE YOUR UI HERE 
           holder.textView.setText(url+ " : " +response.getStatusLine()); 
          } 
         }); 

        } catch (ClientProtocolException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
      }); 

      worker.start(); 


     } 
    }); 

    return convertView; 
} 
+0

Проблема в том, что я не установил нить «final», Спасибо за ваш ответ. –

1

Я предпочитаю держать вещи простыми. Thread и Handler являются важными концепциями java и android соответственно, но выполнение http в ответ на события пользовательского интерфейса настолько распространено в Android, что они изобрели удивительный помощник под названием AsyncTask.

Создайте анонимный экземпляр этого класса с внутренней ссылкой на класс Activity (т. Е. На практике определите класс внутри вашей деятельности и не сделайте его static). Именно эти особенности Java, которые разработчики имели в виду при разработке Android UI и шаблонов нарезания резьбы.

Из приведенных выше документы:

Когда асинхронная задача выполняется, задача проходит через ...

doInBackground(Params...), вызывается на фоновом потоке сразу после onPreExecute() завершения выполнения. Этот шаг используется для выполнения фоновых вычислений, которые могут занять много времени. ...

onPostExecute(Result), invused on the UI нить после завершения вычислений фона. Результат вычисления фона передается на этот шаг в качестве параметра.

[У меня есть дополнительные сведения, также мой акцент].

Ваш адаптер getView должен ссылаться на задачу async, которая передает информацию из кодового блока, выполненного со всеми вашими синхронными HTTP-запросами в ней из потока пользовательского интерфейса, в блок кода в потоке пользовательского интерфейса, который можно использовать для касания его (вы обновляете свой список).

NB Dont»забудьте проверить ListView по-прежнему актуален для этих данных после того, как задача завершена, или из-за AbsListView зрения переработки, вы рискуете положить данные в очевидно неправильную ячейку.

Лучшие,

Tom.

+0

Спасибо за ваш ответ –

Смежные вопросы