使用 AsynkTask 和 Interfaces 的 Android 程序崩溃

Posted

技术标签:

【中文标题】使用 AsynkTask 和 Interfaces 的 Android 程序崩溃【英文标题】:Android program using AsynkTask and Interfaces crash 【发布时间】:2014-01-22 20:44:58 【问题描述】:

我正在编写一个从数据库下载数据的程序,当我使用 onPostExecute 方法获取详细数据时,一切正常。因为我在调用 AsynkTask 类的类中需要这些数据,所以我使用了方法 new AsynkTaskClass.execute().get() 并且它起作用了。最终我实现了一个接口而不是.get() 方法并且程序崩溃了。当我调试它时,它在doInBackground 中调用的方法updateJSONData() 的一行中崩溃,奇怪的是,在该方法中,我在实现接口时没有更改一行。我在this answer.中实现了接口

我在这里放了一些代码:

Register.java:我从中调用扩展 AsynkTask 的类。

package com.PacchettoPrincipale.app;

import [...]

public class Register extends Activity implements OnClickListener

    private EditText user, pass, codDoc;
    private Button  mRegister;

    private ProgressDialog pDialog;

    // Variabile utilizzata per ricevere le fermate attraverso l'interfaccia retrieveHashMapFromAsynkTask
    ArrayList<HashMap<String, String>> fermate;

    // JSON parser class
    JSONParser jsonParser = new JSONParser();

    //testing on Emulator:
    private static final String LOGIN_URL = "http://10.0.2.2/PrimaAppandroid/register.php";

    //ids
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_MESSAGE = "message";


    //not important
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.register);

        user = (EditText)findViewById(R.id.username);
        pass = (EditText)findViewById(R.id.password);
        codDoc = (EditText)findViewById(R.id.codDoc);

        mRegister = (Button)findViewById(R.id.register);
        mRegister.setOnClickListener(this);
    


    @Override
    public void onClick(View v) 

        // HERE is where I call the AsynkTask class
        new LoadFermate(Register.this, new retrieveHashMapFromAsynkTask() 
            @Override
            public void assignment(ArrayList<HashMap<String, String>> returnedValues) 
                fermate = returnedValues;
            
        ).execute();

        for (HashMap<String, String> fermata:fermate)
            Toast.makeText(Register.this , fermata.get("Nome"), Toast.LENGTH_SHORT).show();
        
    

    // is another AsynkTask class, don't look at it.
    class CreateUser extends AsyncTask<String, String, String> [...]


LoadFermate.java是扩展AsynkTask的类,我在程序崩溃的那一行放了一个大写的注释。

package com.PacchettoPrincipale.app;

import [...]

public class LoadFermate extends AsyncTask<Void, Void, ArrayList<HashMap<String, String>>> 

    private Context context;
    private retrieveHashMapFromAsynkTask retrieveListener;

    public LoadFermate(Context context, retrieveHashMapFromAsynkTask retrieveListener)
        this.context = context;
        this.retrieveListener = retrieveListener;
    

    private ProgressDialog pDialog;

    private JSONArray mComments = null;
    private ArrayList<HashMap<String, String>> mCommentList;

    //testing on Emulator:
    private static final String DOWNLOAD_FERMATE_URL = "http://10.0.2.2/PrimaAppAndroid/get/fermate.php";

    //JSON IDS:
    private static final String TAG_COD = "CodFermata";
    private static final String TAG_POSTS = "posts";
    private static final String TAG_NOME = "Nome";

    @Override
    protected void onPreExecute() 
        super.onPreExecute();
        pDialog = new ProgressDialog(context);
        pDialog.setMessage("Download fermate...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    

    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(Void... voids) 
        updateJSONData();
        return mCommentList;
    

    @Override
    protected void onPostExecute(ArrayList<HashMap<String, String>> hashMaps) 
        super.onPostExecute(hashMaps);

        pDialog.dismiss();

        if(retrieveListener != null)
            retrieveListener.assignment(hashMaps);
        
    

    private void updateJSONData() 

        mCommentList = new ArrayList<HashMap<String, String>>();

        JSONParser jParser = new JSONParser();

        //THE PROGRAM CRASHES AT THIS LINE
        JSONObject json = jParser.getJSONFromUrl(DOWNLOAD_FERMATE_URL);

        try 

            mComments = json.getJSONArray(TAG_POSTS);

            for (int i = 0; i < mComments.length(); i++) 
                JSONObject c = mComments.getJSONObject(i);

                int CodFermata = c.getInt(TAG_COD);
                String Nome = c.getString(TAG_NOME);

                HashMap<String, String> map = new HashMap<String, String>();

                map.put(TAG_COD, String.valueOf(CodFermata));
                map.put(TAG_NOME, Nome);

                mCommentList.add(map);
            

         catch (JSONException e) 
            e.printStackTrace();
        


    

retrieveHashMapFromAsynkTask.java:是接口。

package com.PacchettoPrincipale.app;

import java.util.ArrayList;
import java.util.HashMap;

public interface retrieveHashMapFromAsynkTask 
    public void assignment(ArrayList<HashMap<String, String>> returnedValues);

我也放了用Exception这个词过滤的LogCat,这里有很多NullPointerException。我认为这是关键,但我不明白它是从哪里升起的。

Logcat

01-05 05:46:18.460        52-52/? W/dalvikvm﹕ Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Landroid/media/videoeditor/MediaArtistNativeHelper;
01-05 05:47:31.270      382-397/system_process W/BroadcastQueue﹕ Failure sending broadcast Intent  act=android.intent.action.CONFIGURATION_CHANGED flg=0x70000010 
    android.os.TransactionTooLargeException
            at android.os.BinderProxy.transact(Native Method)
            at android.app.ApplicationThreadProxy.scheduleRegisteredReceiver(ApplicationThreadNative.java:1059)
            at com.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:421)
            at com.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:507)
            at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:555)
            at com.android.server.am.BroadcastQueue$1.handleMessage(BroadcastQueue.java:141)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at com.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:1870)
01-05 05:47:31.290      382-397/system_process W/BroadcastQueue﹕ Failure sending broadcast Intent  act=android.intent.action.CONFIGURATION_CHANGED flg=0x70000010 
    android.os.TransactionTooLargeException
            at android.os.BinderProxy.transact(Native Method)
            at android.app.ApplicationThreadProxy.scheduleRegisteredReceiver(ApplicationThreadNative.java:1059)
            at com.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:421)
            at com.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:507)
            at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:555)
            at com.android.server.am.BroadcastQueue$1.handleMessage(BroadcastQueue.java:141)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at com.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:1870)
01-05 05:47:31.310      382-397/system_process W/BroadcastQueue﹕ Failure sending broadcast Intent  act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x50000010 (has extras) 
    android.os.TransactionTooLargeException
            at android.os.BinderProxy.transact(Native Method)
            at android.app.ApplicationThreadProxy.scheduleRegisteredReceiver(ApplicationThreadNative.java:1059)
            at com.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:421)
            at com.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:507)
            at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:555)
            at com.android.server.am.BroadcastQueue$1.handleMessage(BroadcastQueue.java:141)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at com.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:1870)
01-05 05:47:42.750      382-434/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '18 interface fwmark exempt add 10.0.2.2/32' failed with '400 18 Failed to add exemption rule (File exists)'
01-05 05:47:42.870      382-434/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '20 interface fwmark exempt add 10.0.2.3/32' failed with '400 20 Failed to add exemption rule (File exists)'
01-05 05:47:42.920      382-434/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '21 interface route add eth0 secondary 10.0.2.2 32 0.0.0.0' failed with '400 21 ip route modification failed (No such device)'
01-05 05:47:42.960      382-434/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '22 interface route add eth0 secondary 0.0.0.0 0 10.0.2.2' failed with '400 22 ip route modification failed (No such device)'
01-05 05:47:52.480      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '30 interface fwmark exempt add 10.0.2.2/32' failed with '400 30 Failed to add exemption rule (File exists)'
01-05 05:47:52.720      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '32 interface fwmark exempt add 173.194.40.6/32' failed with '400 32 Failed to add exemption rule (File exists)'
01-05 05:47:55.950      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '34 interface fwmark exempt add 10.0.2.2/32' failed with '400 34 Failed to add exemption rule (File exists)'
01-05 05:47:56.080      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '36 interface fwmark exempt add 173.194.40.0/32' failed with '400 36 Failed to add exemption rule (File exists)'
01-05 05:47:57.240      663-678/com.android.systemui W/Binder﹕ Binder call failed.
    android.os.DeadObjectException
            at android.os.BinderProxy.transact(Native Method)
            at android.content.IIntentReceiver$Stub$Proxy.performReceive(IIntentReceiver.java:124)
            at android.app.ActivityThread$ApplicationThread.scheduleRegisteredReceiver(ActivityThread.java:816)
            at android.app.ApplicationThreadNative.onTransact(ApplicationThreadNative.java:394)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)
01-05 05:47:57.270      663-678/com.android.systemui E/JavaBinder﹕ *** Uncaught remote exception!  (Exceptions are not yet supported across processes.)
    java.lang.RuntimeException: android.os.DeadObjectException
            at android.os.Parcel.writeException(Parcel.java:1366)
            at android.os.Binder.execTransact(Binder.java:410)
            at dalvik.system.NativeStart.run(Native Method)
     Caused by: android.os.DeadObjectException
            at android.os.BinderProxy.transact(Native Method)
            at android.content.IIntentReceiver$Stub$Proxy.performReceive(IIntentReceiver.java:124)
            at android.app.ActivityThread$ApplicationThread.scheduleRegisteredReceiver(ActivityThread.java:816)
            at android.app.ApplicationThreadNative.onTransact(ApplicationThreadNative.java:394)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)
01-05 05:47:59.220      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '38 interface fwmark exempt add 10.0.2.2/32' failed with '400 38 Failed to add exemption rule (File exists)'
01-05 05:47:59.320      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '40 interface fwmark exempt add 173.194.40.5/32' failed with '400 40 Failed to add exemption rule (File exists)'
01-05 05:48:02.400      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '42 interface fwmark exempt add 10.0.2.2/32' failed with '400 42 Failed to add exemption rule (File exists)'
01-05 05:48:02.480      382-659/system_process E/ConnectivityService﹕ Exception trying to add a route: java.lang.IllegalStateException: command '44 interface fwmark exempt add 173.194.40.7/32' failed with '400 44 Failed to add exemption rule (File exists)'
01-05 05:57:13.340    1104-1104/? W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb3a5cba8)
01-05 05:57:22.380    1104-1104/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.PacchettoPrincipale.app, PID: 1104
    java.lang.NullPointerException
            at com.PacchettoPrincipale.app.Register.onClick(Register.java:87)
            at android.view.View.performClick(View.java:4438)
            at android.view.View$PerformClick.run(View.java:18422)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
01-05 05:58:03.480      382-571/system_process W/InputMethodManagerService﹕ Got RemoteException sending setActive(false) notification to pid 1104 uid 10052
01-05 05:58:03.500      530-546/com.android.inputmethod.latin W/Binder﹕ Caught a RuntimeException from the binder stub implementation.
    java.lang.NullPointerException
            at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
            at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)
01-05 05:58:16.800      382-575/system_process W/InputMethodManagerService﹕ Got RemoteException sending setActive(false) notification to pid 1136 uid 10052
01-05 05:58:16.890      530-543/com.android.inputmethod.latin W/Binder﹕ Caught a RuntimeException from the binder stub implementation.
    java.lang.NullPointerException
            at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
            at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
            at android.os.Binder.execTransact(Binder.java:404)
            at dalvik.system.NativeStart.run(Native Method)

另一个奇怪的部分是 nullPointer 位于寄存器第 87 行,这是我没有到达调试的行。它在到达之前崩溃:它在doInBackground 期间崩溃,并且Register:87 在onPostExecute 之后执行。

感谢您提前回答!

【问题讨论】:

看起来一切都是从这里开始的:com.PacchettoPrincipale.app.Register.onClick(Register.java:87) 处的 java.lang.NullPointerException 我更新了问题,我忘记了一部分。谢谢你提醒我! 【参考方案1】:

这里是 NullPointerException...

   for (HashMap<String, String> fermata : fermate)
        Toast.makeText(Register.this , fermata.get("Nome"), Toast.LENGTH_SHORT).show();
   

这里fermate 为空。您正在retrieveHashMapFromAsynkTask 回调中初始化fermate,该回调将由AsyncTask 在它的onPostExecute() 中调用。您应该等待 AsyncTask 完成它的任务或将该 Toast 移动到 retrieveHashMapFromAsynkTask 实现...

    new LoadFermate(Register.this, new retrieveHashMapFromAsynkTask() 
        @Override
        public void assignment(ArrayList<HashMap<String, String>> returnedValues) 
            fermate = returnedValues;
            for (HashMap<String, String> fermata:fermate)
                Toast.makeText(Register.this , fermata.get("Nome"), Toast.LENGTH_SHORT).show();
            
        
    ).execute();

【讨论】:

怎么等呢? 只是一个建议......在我的实际项目中,我离开了 Toast,我会做所有这些事情 3 次(我会加载 'fermate'、'tratta' 和 'linea') ,然后我将使用这 3 个数组。我怎样才能等待所有 3 个都被加载并避免其中一个引发 NullPointerException?

以上是关于使用 AsynkTask 和 Interfaces 的 Android 程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript,接口(Interfaces),对象、数组和函数的类型

java中如何使用接口继承(Extending Interfaces)

Effective TestStand Operator Interfaces

同一方法的多个实现,可能与Go和Interfaces具有不同的依赖性

滚动列表时视图意外更改

Ubuntu 18.10 使用VMware克隆后,克隆后的机器再手动更改interfaces配置文件后无法启动网络的解决办法