2015-04-14 1 views
0

все. Я работаю с фиктивным приложением, где я показываю данные, поступающие с web-службы. http://api.openweathermap.org/data/2.5/weather?q=CityName. Все работает нормально, но проблема, с которой я сталкиваюсь, заключается в том, что когда я показываю Toast без данных, поступающих с сервера или когда интернет не может быть доступен на устройстве, мое приложение сбой при эмуляции эмулятора.Отображение тоста без каких-либо данных, возникающих в результате создания веб-службы. Приложение для андроида

"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

Когда вы получаете сообщение об ошибке, в вашем Android-консоли (LogCat) вы должны увидеть трассировку исключения. Скопируйте его здесь (только первые две/три строки, а не полная трасса исключения) –

ответ

1

Проблема вы пытаетесь обновить пользовательский интерфейс от doInBackground. doInBackground работает в фоновом потоке, а не в главном (также называемом потоком пользовательского интерфейса).

Как вы можете прочитать в документации AsyncTask (курсив):

onPreExecute(), вызывается в потоке пользовательского интерфейса прежде, чем задание выполнено. Этот шаг обычно используется для настройки задачи, например, показывая индикатор выполнения в пользовательском интерфейсе.

doInBackground (Params ...), Вызывается на фоне потока сразу после onPreExecute() завершает выполнение. Этот шаг используется для выполнения фоновых вычислений, которые могут занять много времени. Параметры асинхронной задачи передаются на этот шаг. Результат вычисления должен быть возвращен этим шагом и будет возвращен на последний шаг. Этот шаг также может использовать publishProgress (Progress ...) для публикации одного или нескольких единиц прогресса. Эти значения публикуются в потоке пользовательского интерфейса на этапе onProgressUpdate (Progress ...).

onProgressUpdate (Progress ...), , вызываемый в потоке пользовательского интерфейса после вызова publishProgress (Progress ...). Время выполнения не определено.Этот метод используется для отображения любой формы прогресса в пользовательском интерфейсе, пока фоновое вычисление все еще выполняется. Например, его можно использовать для анимации индикатора выполнения или отображения журналов в текстовом поле.

onPostExecute (Result), , вызываемый в потоке пользовательского интерфейса после завершения вычисления фона. Результат вычисления фона передается на этот шаг в качестве параметра.

Так что вам нужно сделать этот тост в другом месте. Например, вы можете определить интерфейс в вашем AsyncTask с помощью метода обратного вызова:

public interface MyTaskInterface { 
    public void onNetworkError(); 
} 

Вы определяете слушатель внутри AsyncTask:

private MyTaskInterface listener; 

Добавить Геттеры & сеттеров для слушателя, и вы можете написать:

if (listener != null) { 
    listener.onNetworkError(); 
} 
1

Возможно, вы не должны делать Toast в «doInbackground». Потому что это не поток пользовательского интерфейса.

Попробуйте сделать это в "onPostExecute".

1

Вы пытаетесь показать тосты в doInBackground. Любые функциональные возможности, связанные с пользовательским интерфейсом, не должны вызываться из этого метода, поскольку это фоновый поток. Вы должны показать тост от onPostExecute.

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(); 


    } 
1

Прежде всего убедитесь, что у вас есть разрешение . Если это правильно, то в год код вы поджариваете сообщение в фоновом потоке. Хотя работа с пользовательским интерфейсом не допускается в фоновом режиме. Таким образом, вы можете использовать метод onPost() для тоста или можете применить ниже код.

runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(getApplicationContext(), "Not able to connect", Toast.LENGTH_LONG).show(); 
       } 
      }); 

Так **runOnUiThread** позволяют сделать работу пользовательского интерфейса от фонового потока. Надеюсь, это вам поможет.