所有。我正在使用虚拟应用程序,我正在显示来自wheather webservice http://api.openweathermap.org/data/2.5/weather?q=CityName的数据。一切正常但我面临的问题是当我显示Toast时没有来自服务器的数据或者当互联网可能无法使用时在设备上我的应用程序在模拟器diplaying中崩溃。
"Unfortunately wheather app stopped working "
只有在设备上没有互联网时才会出现此问题。当我断开互联网连接时为我创建问题的界限是这样的:
Toast.makeText(getApplicationContext(), "Not able to connect", Toast.LENGTH_LONG).show();
如果我评论此行,我的应用程序工作正常。我在这个文件上的所有代码都是这样的:
package com.mubu.wheathertoday.wheathertoday;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
import org.w3c.dom.Text;
public class MainActivity extends ActionBarActivity {
EditText etCity;
Button btnShow;
ProgressDialog pbar;
String JsonString;
TextView tvr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etCity=(EditText)findViewById(R.id.etCity);
btnShow=(Button)findViewById(R.id.btnShow);
btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncGetData gd=new AsyncGetData();
gd.execute();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class AsyncGetData extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
try {
ServiceHandler sh = new ServiceHandler();
String url="http://api.openweathermap.org/data/2.5/weather?q="+etCity.getText().toString().trim();
JsonString = sh.makeServiceCall(url, ServiceHandler.POST);
if (JsonString != null) {
Intent i=new Intent(getApplicationContext(),WheatherActivity.class);
try{
i.putExtra("jsn",JsonString);
i.putExtra("city",etCity.getText().toString());
startActivity(i);
}catch (Exception e){
}
}
else
{
try{
Toast.makeText(getApplicationContext(), "Not able to connect", Toast.LENGTH_LONG).show();
// if I disconnect Internet this line gets executed and my app crashes
}catch (Exception e){
}
}
}
catch (Exception e){etCity.setText(e.getMessage());}
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pbar=new ProgressDialog(MainActivity.this);
pbar.setMessage("Please wait...");
pbar.setCancelable(false);
pbar.show();
}
@Override
protected void onPostExecute(Void s) {
super.onPostExecute(s);
if(pbar.isShowing() )
pbar.dismiss();
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
}
答案 0 :(得分:1)
也许你不应该在“doInbackground”中制作Toast。因为它不是UI线程。
尝试在“onPostExecute”中执行此操作。
答案 1 :(得分:1)
您正试图在doInBackground
中展示Toast。不应该从此方法调用任何与UI相关的功能,因为这是后台线程。你必须从onPostExecute
开始祝酒。
答案 2 :(得分:1)
问题是您是否正在尝试从doInBackground
更新用户界面。 doInBackground
在后台线程中运行,而不在main(也称为UI线程)中运行。
正如您可以阅读AsyncTask文档(强调我的):
在执行任务之前,onPreExecute(),在UI线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。
在onPreExecute()完成执行后,doInBackground(Params ...),在后台线程上立即调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数将传递给此步骤。计算结果必须由此步骤返回,并将传递回最后一步。此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单元。这些值发布在UI线程的onProgressUpdate(Progress ...)步骤中。
在调用publishProgress(Progress ...)之后,onProgressUpdate(进度...),在UI线程上调用。执行的时间是不确定的。此方法用于在后台计算仍在执行时显示用户界面中的任何形式的进度。例如,它可用于为进度条设置动画或在文本字段中显示日志。
在后台计算完成后,onPostExecute(Result),在UI线程上调用。后台计算的结果作为参数传递给此步骤。
所以你需要在其他地方做那个吐司。例如,您可以使用回调方法在Asynctask中定义接口:
public interface MyTaskInterface {
public void onNetworkError();
}
您在AsyncTask中定义一个侦听器:
private MyTaskInterface listener;
添加吸气剂&amp;听众的设定者,你可以写:
if (listener != null) {
listener.onNetworkError();
}
答案 3 :(得分:1)
首先请确保您拥有互联网权限。 如果它是正确的那么每年代码你在背景线程上烘烤一条消息。 虽然在后台不允许使用UI工作。 因此,您可以使用onPost()方法加密消息,也可以应用以下代码。
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Not able to connect", Toast.LENGTH_LONG).show();
}
});
所以**runOnUiThread**
允许我们从后台线程执行UI操作。我希望它可以帮到你。
答案 4 :(得分:0)
你正在做的是在背景中显示吐司,你不能这样做,如果你想要显示吐司,你必须在onPostExecute中编写那段代码
你可以做的是你必须创建一个布尔变量,因为asyntask calss假设命名为_Is_Responce_Received = false;
并在
if (JsonString != null) {
_Is_Responce_Received=true;
// rest of your code
}
并在你的帖子中执行
@Override
protected void onPostExecute(Void s) {
super.onPostExecute(s);
if(!_Is_Responce_Received){
Toast.makeText(getApplicationContext(), "Not able to connect", Toast.LENGTH_LONG).show();
}
if(pbar.isShowing() )
pbar.dismiss();
}