我正在编写一个Android应用程序,我之前遇到了问题NetworkOnMainThreadException
并且我使用线程解决了问题。我现在没有得到任何错误,也没有得到任何输出。
这是我的代码:LogCat中没有错误
public class Currency_convert extends Activity {
public int to;
public int from;
public String [] val;
public String s;
public Handler handler;
public double am=0.0;
StringBuilder build=null ;
HttpClient client=null;
HttpGet httpGet =null;
HttpResponse response=null;
HttpEntity entity=null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.currency);
Spinner s1 = (Spinner) findViewById(R.id.spinner11);
Spinner s2 = (Spinner) findViewById(R.id.spinner22);
final EditText e=(EditText) findViewById(R.id.amountt);
// am=Double.parseDouble(e.getText().toString());
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.name, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);
val = getResources().getStringArray(R.array.value);
s1.setAdapter(adapter);
s2.setAdapter(adapter);
s1.setOnItemSelectedListener(new spinOne(1));
s2.setOnItemSelectedListener(new spinOne(2));
Button b = (Button) findViewById(R.id.button11);
b.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
TextView t = (TextView) findViewById(R.id.textView44);
if(from == to) {
Toast.makeText(getApplicationContext(), "Invalid", 4000).show();
}
else {
try {
s = getJson("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22"+val[from]+val[to]+"%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=");
//s=getJson("http://www.google.com/ig/calculator?hl=en&q=1USD=?INR");
JSONObject jObj;
jObj = new JSONObject(s);
String exResult = jObj.getJSONObject("query").getJSONObject("results").getJSONObject("rate").getString("Rate");
am=Double.parseDouble(e.getText().toString());
double totalR=(Double.parseDouble(exResult))*am;
String r=String.valueOf(totalR);
t.setText(r);
// Log.println(priority, tag, msg)
System.out.println("r =" +r);
Log.i("hello", r);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
public String getJson(final String url)throws ClientProtocolException, IOException {
// private String getJson(String url)throws ClientProtocolException, IOException e {
build = new StringBuilder();
client = new DefaultHttpClient();
httpGet = new HttpGet(url);
new Thread(new Runnable() {
public void run() {
try {
response = client.execute(httpGet);
entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String con;
while ((con = reader.readLine()) != null) {
build.append(con);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// response = client.execute(httpGet);
// entity = response.getEntity();
// InputStream content = entity.getContent();
// BufferedReader reader = new BufferedReader(new InputStreamReader(content));
// String con;
// while ((con = reader.readLine()) != null) {
// build.append(con);
// }
return build.toString();
//return url;
}
private class SpinOne implements OnItemSelectedListener {
int ide;
SpinOne(int i) {
ide =i;
}
public void onItemSelected(AdapterView<?> parent, View view,
int index, long id) {
if(ide == 1) {
from = index;
}
else if(ide == 2) {
to = index;
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}}
答案 0 :(得分:3)
编写它的方式,getJson()
将立即返回,而没有给线程完全运行的时间,因此返回的值将不是您想要的。使用AsyncTask,这样您就可以在AsyncTask的doInBackground()
方法中运行线程代码,然后将结果传递给onPostExecute()
方法,然后您可以根据需要执行setText()
。
另一种方法是在发出HTTP请求后将JSON解析和setText()
代码移动到线程的run()
方法中,但是因为运行与UI相关的代码(在本例中为setText()
)在单独的线程中,您不能使用Handler来安排setText()
在UI线程中运行。
您可以阅读AsyncTask
和Handler
here上的基础知识。
答案 1 :(得分:1)
当您生成一个线程时,代码执行会分成不同的时间范围,因此即使共享全局范围,如果您没有实现某些逻辑,也不会及时为UI更新任务填充对象防止不一致。
Android提供内置的多流控制和线程间通信模式,可以帮助您解决此类不一致问题。其中一个选项涉及AsyncTask,在您的情况下,您可以执行以下操作:
您可以在此answear中查找AsyncTask的示例,以获得实用的方法。
注意:如果要在AsyncTask实例中使用父类成员(如findViewByID),则需要使用<UIThreadName>.this.
手动调用父文件范围,例如: <UIThreadName>.this.findViewByID(id)
。您可以在onPostExecute中自由地执行此操作,该操作由于在UI线程上运行而没有任何限制,但您只能在doInBackground中执行UI更改(不能在UI线程上运行)。
答案 2 :(得分:0)
我解决了它,我刚刚在线程声明后添加了t.join:)