【问题标题】:Android: App crashing when it reaches AlertDialog.Builder using Post methodAndroid:应用程序在使用 Post 方法到达 AlertDialog.Builder 时崩溃
【发布时间】:2015-04-08 08:04:50
【问题描述】:

我在我的 android 应用程序中收到带有正确文本的警报时遇到问题。我使用相同的代码向服务器发送 Get 请求,它工作正常,但在这种情况下,我使用 Post 方法,而我发送的数据存储在数据库中,Logcat 显示出现了正确/预期的字符串返回,应用程序在到达 onPostExecute 部分时会崩溃,而不是显示警报。

我是否遗漏了什么,是否有其他方法可以处理来自 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);

在第二个 if 子句中,意味着它通过了

results.equals("1")

检查,在它失败之前。

谢谢。

【问题讨论】:

    标签: android android-asynctask nullpointerexception android-alertdialog


    【解决方案1】:

    问题在于,不能保证在调用onPostExecute() 时存在活动。

    onPostExecute()是后台线程处理完成后调用的方法,与Activity的生命周期无关。

    解决方法是检查当时是否存在activity,然后执行预期的逻辑。

    您可以查看this 以获得更详细的答案(不同的情况,但都与您在此处遇到的核心问题有关)。还有一篇博文详细定义了这个主题,here

    【讨论】:

      【解决方案2】:

      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

      【讨论】:

        【解决方案3】:

        一年后,但如果其他人有这个问题,也许这个解决方案可以提供帮助。

        当活动要显示对话框或任何需要活动上下文的操作时,务必先检查活动是否可见。

        为此,您需要一个从 Application 扩展的类:

        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
        }
        

        祝你有美好的一天! :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-12
          • 1970-01-01
          • 2020-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多