我是Android开发的新手。当我创建我的第一个程序时,我只是在主线程上运行所有内容,因为它们是非常小的应用程序。我已经开始在我的应用程序中使用Web API,并且知道处理网络的任何事情都应该有自己的线程。我已经尝试过使用AsyncTasks和使用线程和处理程序的多个示例,但是我在将它应用到我自己的代码时遇到了问题,因此我将它带到这里以获取有关如何对我目前所拥有的内容进行线程化的想法和建议。
快速代码概述:我正在接收来自其他活动的输入,并根据该输入创建Web API的HTTP请求。我收到JSON,然后拿出一个身份证号码。然后,我必须使用ID号向Web API发出另一个HTTP请求,然后我解析JSON并创建一个数组适配器以在我的活动中显示一个列表。
package com.example.myfirstapp;
imports ....
public class BREWERYMessageActivity extends ListActivity {
//Variable from another Activity
public final static String BREWERY_MESSAGE = "com.example.myfirstapp.BREWERY";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
final String brewery = intent.getStringExtra(MainActivity.BREWERY_MESSAGE);
try {
URL breweryDBurl = new URL("web api url using brewery variable");
URLConnection conn = breweryDBurl.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
conn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
JSONObject jsonobject = new JSONObject(inputLine);
JSONArray jArray = jsonobject.getJSONArray("data");
JSONObject obj1 = (JSONObject)jArray.getJSONObject(0);
String ID;
try{
ID = obj1.getString("id");
}catch(Exception e){
ID = "N/A";
}
try {
URL DBurl = new URL("Second web API call using the ID");
URLConnection con = DBurl.openConnection();
BufferedReader inpt = new BufferedReader(
new InputStreamReader(
con.getInputStream()));
String inputLn;
ArrayList<String> stringList = new ArrayList<String>();
while ((inputLn = inpt.readLine()) != null) {
JSONObject jsonobj = new JSONObject(inputLn);
JSONArray jArry = jsonobj.getJSONArray("data");
String name;
for(int i = 0; i < jArry.length(); i++){
JSONObject obj = (JSONObject)jArry.getJSONObject(i);
try{
name = obj.getString("name");
} catch(Exception e) {
name = "N/A";
}
if(!(name.equals("N/A")))
stringList.add(name);
}
name = "";
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(BREWERYMessageActivity.this,android.R.layout.simple_list_item_1, stringList);
setListAdapter(adapter);
}catch(Exception e){
// Create the text view
TextView textView = new TextView(BREWERYMessageActivity.this);
textView.setTextSize(20);
textView.setText("Not Available");
textView.setGravity(Gravity.CENTER_HORIZONTAL);
// Set the text view as the activity layout
setContentView(textView);
}
}
}catch(Exception e){
// Create the text view
TextView textView = new TextView(BREWERYMessageActivity.this);
textView.setTextSize(20);
textView.setText("Not Available");
textView.setGravity(Gravity.CENTER_HORIZONTAL);
// Set the text view as the activity layout
setContentView(textView);
}
}
答案 0 :(得分:1)
我建议你使用AsyncTask。所以在doInBackground中,你真的无法在UI中更新任何内容,例如像按钮,TextViews等视图......
如有必要,可使用onPreExecute,onProgressUpdate和onPostExecute更新用户界面线程。
E.g。将URL breweryDBurl = new URL("web api url using brewery variable");
以后的代码块放在doInBackground方法ArrayAdapter<String> adapter = new ArrayAdapter<String>(BREWERYMessageActivity.this,android.R.layout.simple_list_item_1, stringList);
内,并将适配器返回到onPostExecute内的setListAdapter(adapter);
。
本文非常适合AsyncTask及所有功能。
http://developer.android.com/reference/android/os/AsyncTask.html
答案 1 :(得分:1)
除了Marcelo的回答之外,你永远不应该更改listadapter或在UI线程之外的任何其他线程中创建它的值。
因此,在doinbackground(你的stringList)中创建一个新的值列表更安全,然后在onPostExecute中创建ArrayAdapter并调用setlistadapter,而不是在doInBackground中创建arrayadapter。
否则你会倾向于
适配器的内容已更改,但ListView未收到通知。 确保未从后台线程修改适配器的内容,但是 仅来自UI线程。
错误。这是一个非常不规律地出现的错误(它只是在像马塞洛说的那样工作了很长一段时间才发生在我身上,我一整天都没有意识到它不时发生,直到它不时开始发生)