すべて。ウェブサービスhttp://api.openweathermap.org/data/2.5/weather?q=CityNameからのデータを表示しているダミーアプリケーションを使用しています。すべて正常に機能していますが、直面している問題は、表示するときに発生することです。サーバーからのデータがない場合、またはデバイスでインターネットが利用できない場合にトーストすると、エミュレーターの表示中にアプリがクラッシュします。
"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);
}
}
}
問題は、からユーザーインターフェイスを更新しようとしていることですdoInBackground
。doInBackground
メインではなく、バックグラウンドスレッド(UIスレッドとも呼ばれます)で実行されます。
AsyncTaskのドキュメント(私の強調)で読むことができるように:
onPreExecute()は、タスクが実行される前にUIスレッドで呼び出されます。このステップは通常、タスクをセットアップするために使用されます。たとえば、ユーザーインターフェイスに進行状況バーを表示します。
doInBackground(Params ...)、onPreExecute()の実行が終了した直後にバックグラウンドスレッドで呼び出されます。このステップは、時間がかかる可能性のあるバックグラウンド計算を実行するために使用されます。非同期タスクのパラメーターは、このステップに渡されます。計算の結果はこのステップで返される必要があり、最後のステップに戻されます。このステップでは、publishProgress(Progress ...)を使用して、1つ以上の進行状況を公開することもできます。これらの値は、UIスレッドのonProgressUpdate(Progress ...)ステップで公開されます。
onProgressUpdate(Progress ...)、publishProgress(Progress ...)の呼び出し後にUIスレッドで呼び出されます。実行のタイミングは未定義です。このメソッドは、バックグラウンド計算の実行中に、ユーザーインターフェイスで進行状況を表示するために使用されます。たとえば、プログレスバーをアニメーション化したり、テキストフィールドにログを表示したりするために使用できます。
onPostExecute(Result)、バックグラウンド計算の終了後にUIスレッドで呼び出されます。バックグラウンド計算の結果は、パラメーターとしてこのステップに渡されます。
だからあなたは他の場所でそのトーストをする必要があります。たとえば、コールバックメソッドを使用してAsynctask内にインターフェイスを定義できます。
public interface MyTaskInterface {
public void onNetworkError();
}
AsyncTask内でリスナーを定義します。
private MyTaskInterface listener;
リスナーのゲッターとセッターを追加すると、次のように書くことができます。
if (listener != null) {
listener.onNetworkError();
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加