【问题标题】:Call setListAdapter from a different class file从不同的类文件调用 setListAdapter
【发布时间】:2013-02-19 15:45:02
【问题描述】:

我有一个这样的类文件:

public class Search_Results extends SherlockListActivity{

     String result = "";
     SearchView searchView;
     Context context = this;
     private Intent intent = null;
     private String searchThis = "";

      @Override
      protected void onCreate(Bundle savedInstanceState){
             super.onCreate(savedInstanceState);
             setTheme(R.style.Sherlock___Theme_DarkActionBar);
             setContentView(R.layout.search_results);
             ListView myList=(ListView)findViewById(android.R.id.list);
             ProgressBar progress = (ProgressBar)findViewById(R.id.progress_spin);
             intent = getIntent();
             searchThis = intent.getStringExtra(Home.SEARCH_SERVICE);
             new Retrieve(context, progress, searchThis, myList).execute("");
      }//onCreate
}

这会调用另一个 java 文件中的新 Retrieve() 并扩展 AsyncTask

public class Retrieve extends AsyncTask <String, Integer, ArrayList<String>>{

     private Context context;
     private String title = "";
     private ArrayList<String> list = null;
     private ArrayList<NameValuePair> nameValuePairs = null;
     private String result = "";
     private ProgressBar progress;
     private String searchThis;
     private ListView mylist;

     //constructor
     public Retrieve(Context context, ProgressBar progress, String searchThis, ListView myList) {
         this.context = context;
         this.progress = progress;
         this.searchThis = searchThis;
         this.mylist = myList;
     }
protected ArrayList<String> doInBackground(String... params){
            progress.setVisibility(View.VISIBLE);
            InputStream is = null;
            list = new ArrayList<String>();
            nameValuePairs = new ArrayList<NameValuePair>();
            nameValuePairs.add(new BasicNameValuePair("searchThis", searchThis));
            try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(URL);
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();
            }
            catch(Exception e){
                Log.e("CONNECTION_ERROR", "Error in http connection "+e.toString());
            }
            try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null){
                    sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();
            }
            catch(Exception e){
                Log.e("BUFFER_ERROR", "Error converting result "+e.toString());
            }
            if(result.equalsIgnoreCase("null\n")){
                list.add("empty");
            }
            else{
                try{
                    JSONArray jArray = new JSONArray(result);
                    for(int i=0;i<jArray.length();i++){
                        JSONObject json_data = jArray.getJSONObject(i);
                        title = json_data.getString("title");
                        list.add(title);
                    }
                }
                catch(JSONException e){
                    Log.e("DATA_PARSING_ERROR", "Error parsing data "+e.toString());
                }
            }
            return list;
        }

     @Override
     protected void onPostExecute(ArrayList<String> list){
         progress.setVisibility(View.GONE);
         ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(context, R.layout.list_display, list);
         //PROBLEM
         mylist.setAdapter(mArrayAdapter);
     }

 }//Retrieve

我首先只尝试了setListAdapter(mArrayAdapter),但显然 java 不知道要更新的列表,然后我尝试将列表传递给构造函数

ListView myList=(ListView)findViewById(android.R.id.list);

我得到这个错误:

android.view.ViewRootImpl$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views.

也许是因为我试图改变另一个班级的观点?我该如何解决这个问题? onPostExecute 函数是否应该返回 mArrayAdapter?这如何实现?

【问题讨论】:

  • 发布你的 doInBackground 方法代码
  • 我会在早上编辑代码,因为我现在没有它。
  • 好的,因为你在 doInBackground 而不是 onPostExecute 内部有问题
  • 我编辑了 doInBackground 函数的代码。

标签: android android-asynctask listadapter


【解决方案1】:

您收到 Only the original thread that created a view hierarchy can touch its views. 是因为您尝试从 doInBackground 访问 UI 元素。所以只需将它从 doInBackground 移到外面,然后将它移到 onPreExecute 里面:

 @Override
    protected void onPreExecute() {
        super.onPreExecute();
         progress.setVisibility(View.VISIBLE); //<< set here
    }

【讨论】:

    【解决方案2】:

    您可能希望创建适配器并将其设置在您的 Search_Results 活动中。列表的适配器应该是列表所在的 Activity 的组件。您要避免将 UI 与这样的 AsyncTask 紧密耦合,即您的 Retrieve 类只需要完成工作并返回,不知道有关的详细信息它得到的数据会发生什么。

    我会在 Search_Results 中创建一个公共方法(例如,updateAdapter),您可以从 onPostExecute 方法中调用它。您可以从 Retrieve 类的 context 成员变量中调用它:

    public void updateAdapter(ArrayList<String> list) {
        ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(Search_Results.this, R.layout.list_display, list);
        setListAdapter(mArrayAdapter);
    }
    

    onPostExecute:

    @Override
    protected void onPostExecute(ArrayList<String> list){
        progress.setVisibility(View.GONE);
        context.updateAdapter(list);
    }
    

    【讨论】:

    • 您的解决方案似乎是最优雅的,但我有一个问题,context.updateAdapter(list); eclipse 告诉我该方法未定义类型 Context 并且作为对 Context 变量进行强制转换的建议,我尝试了将上下文作为 this 和 Search_Results.this 传递。
    • 您也许可以将“上下文”变量转换为 Activity,即 Activity 活动 = (Activity) 上下文;然后调用activity.updateAdapter(list);
    • 好的,谢谢,不过有个问题,既然我明确设置了上下文,JVM 不应该能够识别出我正在调用另一个类中存在的函数吗?
    • 我认为这与它被设置为“上下文”对象有关,而不是明确的“活动”。您尝试调用的方法仅在 Activity 级别可用,而不是 Context 类的方法。所以你需要明确地转换它。经过审查(我之前的评论很仓促),我认为您需要转换为特定的“Search_Results”活动,而不是更通用的“活动”。
    【解决方案3】:

    您可以将ListActivity 对象而不是ListView 传递给您的Retrieve 构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 2010-11-18
      • 1970-01-01
      • 2018-03-29
      相关资源
      最近更新 更多