3

У меня проблемы с получением предупреждения в приложении для Android с правильным текстом. Я использую тот же код для отправки запроса Get на серверы, и он работает нормально, но в этом случае я использую метод Post, а в то время как данные, которые я отправляю, хранятся в базе данных, а Logcat показывает, что появляется правильная/ожидаемая строка back, приложение просто падает, когда оно попадает на часть onPostExecute вместо отображения предупреждения.Android: приложение разбивается, когда оно достигает AlertDialog.Builder, используя метод Post

Я что-то упустил, есть ли другой способ обработки ответов из метода Post?

Вот мой код:

package com.example.aplikacija; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.protocol.BasicHttpContext; 
import org.apache.http.protocol.HttpContext; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.DialogInterface; 
import android.os.AsyncTask; 
import android.text.Html; 
import android.util.Log; 

public class REST_VpisOcene extends AsyncTask<Void, Void, String> { 

String restURL =  "*REST IP removed*"; 

private Activity activity; 
private String predmet; 
private String ocena; 
private String IDucenca; 
private String IDprofesorja; 

public REST_VpisOcene(String predmet, String ocena, String IDucenca, String IDprofesorja, 
     Activity activity) { 
    this.predmet = predmet; 
    this.ocena = ocena; 
    this.IDucenca = IDucenca; 
    this.IDprofesorja = IDprofesorja; 
    this.activity = activity; 
} 

protected String getASCIIContentFromEntity(HttpEntity entity) 
     throws IllegalStateException, IOException { 
    InputStream in = entity.getContent(); 
    StringBuffer out = new StringBuffer(); 
    int n = 1; 
    while (n > 0) { 
     byte[] b = new byte[4096]; 
     n = in.read(b); 
     if (n > 0) 
      out.append(new String(b, 0, n)); 
    } 
    return out.toString(); 
} 

@Override 
protected String doInBackground(Void... params) { 

    String sporocilo = ""; 
    HttpClient httpclient = new DefaultHttpClient(); 
    HttpContext localContext = new BasicHttpContext(); 
    HttpPost httppost = new HttpPost(restURL); 
    httppost.addHeader("Accept", "text/html"); 
    try { 
     List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); 
     nameValuePairs 
       .add(new BasicNameValuePair("predmet", predmet)); 
     nameValuePairs.add(new BasicNameValuePair("ocena", ocena)); 
     nameValuePairs.add(new BasicNameValuePair("IDucenca", IDucenca)); 
     nameValuePairs.add(new BasicNameValuePair("IDprofesorja", IDprofesorja)); 
     httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 

     HttpResponse response = httpclient.execute(httppost, localContext); 
     HttpEntity entity = response.getEntity(); 
     sporocilo = getASCIIContentFromEntity(entity); 
    } catch (ClientProtocolException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    Log.i("odgovor vpisa", sporocilo); 
    return sporocilo; 

} 

protected void onPostExecute(String results) { 
    if (results.equals("0")) { 



     AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
     builder.setMessage("Pri vpisu je prišlo do napake!") 
       .setCancelable(false) 
       .setNegativeButton("OK", 
         new DialogInterface.OnClickListener() { 
          public void onClick(DialogInterface dialog, 
            int id) { 
           dialog.cancel(); 
          } 
         }); 
     AlertDialog alert = builder.create(); 
     alert.show(); 
    } else if (results.equals("1")) { 

     AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
     builder.setMessage("Vpisano!") 
       .setCancelable(false) 
       .setNegativeButton("OK", 
         new DialogInterface.OnClickListener() { 
          public void onClick(DialogInterface dialog, 
            int id) { 
           dialog.cancel(); 
          } 
         }); 
     AlertDialog alert = builder.create(); 
     alert.show(); 
    } 
} 
} 

И мой Logcat:

02-08 14:56:11.856: I/odgovor vpisa(6424): 1 
02-08 14:56:11.859: D/AndroidRuntime(6424): Shutting down VM 
02-08 14:56:11.860: E/AndroidRuntime(6424): FATAL EXCEPTION: main 
02-08 14:56:11.860: E/AndroidRuntime(6424): Process: com.example.aplikacija,  PID: 6424 
02-08 14:56:11.860: E/AndroidRuntime(6424): java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:154) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.app.AlertDialog$Builder.<init>(AlertDialog.java:379) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at com.example.aplikacija.REST_VpisOcene.onPostExecute(REST_VpisOcene.java:121) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at com.example.aplikacija.REST_VpisOcene.onPostExecute(REST_VpisOcene.java:1) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.os.AsyncTask.finish(AsyncTask.java:632) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.os.AsyncTask.access$600(AsyncTask.java:177) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.os.Handler.dispatchMessage(Handler.java:102) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.os.Looper.loop(Looper.java:135) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at android.app.ActivityThread.main(ActivityThread.java:5221) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at java.lang.reflect.Method.invoke(Native Method) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at java.lang.reflect.Method.invoke(Method.java:372) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
02-08 14:56:11.860: E/AndroidRuntime(6424):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

Это не будет работать на линии 121, которая является

AlertDialog.Builder builder = new AlertDialog.Builder(activity); 

во втором случае п, что он получает через

results.equals("1") 

проверить, прежде чем он не сработает.

спасибо.

ответ

10

Проблема заключается в том, что не гарантируется, что активность присутствует в момент вызова onPostExecute().

onPostExecute() - это метод, который вызывается после обработки фонового потока, независимо от жизненного цикла Activity.

Решение состоит в том, чтобы проверить, присутствует ли в данный момент активность, а затем выполнить предполагаемую логику.

Вы можете увидеть this для более подробного ответа (в другой ситуации, но оба связаны с основной проблемой, которую вы здесь). Существует также сообщение в блоге, которое подробно описывает этот вопрос, который доступен here.

0

изменение private Activity context; к private Context context

и

public REST_VpisOcene(String predmet, String ocena, String IDucenca, String IDprofesorja, 
     Context context) { 
    this.predmet = predmet; 
    this.ocena = ocena; 
    this.IDucenca = IDucenca; 
    this.IDprofesorja = IDprofesorja; 
    this.context= context; 
} 

или использовать getApplicationContext() вместо контекста, а также увидеть this Question

2

Через год, но если кто-то есть эта проблема может быть это решение может помочь.

Когда в ходе действия будет показано диалоговое окно или любое действие, требующее контекста активности, важно проверить, есть ли вид активности или нет.

Для достижения этой цели, вам нужен класс, который наследуется от применения:

public class App extends Application { 

    private static Context mContext; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     mContext = this; 
    } 

    public static Context getContext(){ 
     return mContext; 
    } 

    public static boolean isActivityVisible() { 
     return activityVisible; 
    } 

    public static void activityResumed() { 
     activityVisible = true; 
    } 

    public static void activityPaused() { 
     activityVisible = false; 
    } 

    private static boolean activityVisible; 
} 

В классе MainActivity, вам необходимо зарегистрировать текущее состояние приложения, когда некоторые из этих действий сделано:

@Override 
protected void onResume() { 
    super.onResume(); 
    App.activityResumed(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    App.activityPaused(); 
} 

И, наконец, прежде чем делать какие-то действия, как показано диалоговое окно, просто проверить, если приложение является видимым:

if (App.isActivityVisible()) { 
    // We can show the dialog 
} else { 
    // Better not show the dialog to avoid a crash 
} 

Имейте славный день! :)

Смежные вопросы