异步任务中发生异常

时间:2012-05-07 04:40:33

标签: java android multithreading android-asynctask android-activity

我得到了这个例外。什么时候,我正在尝试运行我的程序。在我的程序中,我正在执行AsyncTask对于每个下载和上传任务,我创建了新的AsyncTask对象,并尝试在后台运行它。我试图找到我的错误。但我无法找到我错的地方。下面是我的堆栈跟踪和我的程序代码 -

05-07 10:00:44.899: E/AndroidRuntime(367): FATAL EXCEPTION: AsyncTask #1
05-07 10:00:44.899: E/AndroidRuntime(367): java.lang.RuntimeException: An error occured while executing doInBackground()
05-07 10:00:44.899: E/AndroidRuntime(367):  at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.FutureTask.run(FutureTask.java:138)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.lang.Thread.run(Thread.java:1019)
05-07 10:00:44.899: E/AndroidRuntime(367): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-07 10:00:44.899: E/AndroidRuntime(367):  at android.os.Handler.<init>(Handler.java:121)
05-07 10:00:44.899: E/AndroidRuntime(367):  at android.widget.Toast.<init>(Toast.java:68)
05-07 10:00:44.899: E/AndroidRuntime(367):  at android.widget.Toast.makeText(Toast.java:231)
05-07 10:00:44.899: E/AndroidRuntime(367):  at com.android.test.Helper.downloadTask(t.java:269)
05-07 10:00:44.899: E/AndroidRuntime(367):  at com.android.test.Helper.doInBackground(t.java:132)
05-07 10:00:44.899: E/AndroidRuntime(367):  at com.android.test.Helper.doInBackground(t.java:1)
05-07 10:00:44.899: E/AndroidRuntime(367):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-07 10:00:44.899: E/AndroidRuntime(367):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
05-07 10:00:44.899: E/AndroidRuntime(367):  ... 4 more

这是我的AsynTask Helper

class Helper extends AsyncTask<Integer, Void, Void> 
{
    private SmbFile dfile;
    private String dfilepath;
    private SmbFile dfolder;
    private String dfolderpath;
    private File ufolder;
    private SmbFile ufoldersmb;
    private NtlmPasswordAuthentication auth;
    private int upstate=0;
    private int downstate=0;
    private Context context;
    private ArrayList<SmbFile> smbArray=new ArrayList<SmbFile>();
    private String ext;
    private int tasknumber;
    private String taskname;
    public Context getcontext()
    {
        return context;
    }
    public int gettasknumber()
    {
        return tasknumber;
    }
    public String gettaskname()
    {
        return taskname;
    }
    public int getupstate() 
    {
        return upstate;
    }
    public int getdownstate() 
    {
        return downstate;
    }
    public void setdfile(SmbFile a) 
    {
        this.dfile = a;
    }
    public void setdfilepath(String b) 
    {
        this.dfilepath = b;
    }
    public void setdfolder(SmbFile c) 
    {
        this.dfolder = c;
    }
    public void setdfolderpath(String d) 
    {
        this.dfolderpath = d;
    }
    public void setufolder(File g) 
    {
        this.ufolder = g;
    }
    public void setufoldersmb(SmbFile h) 
    {
        this.ufoldersmb = h;
    }
    public void setauthentication(NtlmPasswordAuthentication i) 
    {
        this.auth = i;
    }
    public void setupstate(int j) 
    {
        upstate = j;
    }
    public void setdownstate(int k) 
    {
        downstate = k;
    }
    public void setcontext(Context l) 
    {
        context = l;
    }
    public void setarraysmb(SmbFile m) 
    {
        this.smbArray.add(m);
    }
    public void setextstorage(String n) 
    {
        this.ext=n;
    }
    public void settasknumber(int o) 
    {
        this.tasknumber=o;
    }
    public void settaskname(String p) 
    {
        this.taskname=p;
    }
    @Override
    protected Void doInBackground(Integer... params) 
    {
        //check flag to execute exactly method
        switch (params[0]) 
        {
            case 0:
                downloadTask();
                break;
            case 1:
                Toast.makeText(context, "AccessPC Upload task "+tasknumber+" Started", Toast.LENGTH_LONG).show();
                uploadFolder(ufolder,ufoldersmb);
                break;
            default:break;
        }
        return null;
    }
    void downloadFile(SmbFile dfile,String dpath)
    {   
        StatFs statFs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath()); 
        long blockSize = statFs.getBlockSize();
        long freeSize = statFs.getFreeBlocks()*blockSize;
        try
        {
            if(!((freeSize-dfile.length())<0))
            {
                SmbFileInputStream din=new SmbFileInputStream(dfile);
                FileOutputStream dout=new FileOutputStream(dpath);
                int c;
                while((c=din.read())!=-1)
                {
                    dout.write(c);
                }
                if (din != null) 
                {
                    din.close();
                }
                if (dout != null) 
                {
                    dout.close();
                }
            }
            else
            {
                Toast.makeText(context, "AccessPC Download Task failed ",Toast.LENGTH_LONG).show();
            }
        }
        catch(Exception e)
        {
            Toast.makeText(context, "AccessPC Download Task failed "+e,Toast.LENGTH_LONG).show();
        }
    }
    void downloadFolder(SmbFile dfolder,String dfolderpath)
    {
        try 
        {
            dfolderpath=dfolderpath+dfolder.getName();
            if(!(new File(dfolderpath)).exists())
            {
                (new File(dfolderpath)).mkdir();
            }
            SmbFile[] temp=dfolder.listFiles(); 
            if(temp.length==0)
            {
                Toast.makeText(context, "df,downstate="+downstate,Toast.LENGTH_LONG).show();
                return;
            }
            for(SmbFile m:temp)
            {
                if(m.isFile())
                {
                    downloadFile(m,dfolderpath+m.getName());
                }
                else
                {
                    downloadFolder(m,dfolderpath);
                }
            }
        } 
        catch (Exception e) 
        {
            Toast.makeText(context, "AccessPC Download Task failed "+e,Toast.LENGTH_LONG).show();
        }
    }
    void uploadFile(File ufile,SmbFile ufilesmb)
    {
        try
        {
            FileInputStream uin=new FileInputStream(ufile);
            SmbFile tempSmb=new SmbFile(ufilesmb.getPath()+ufile.getName(),auth);
            SmbFileOutputStream uout=new SmbFileOutputStream(tempSmb);
            int c;
            while((c=uin.read())!=-1)
            {
                uout.write(c);
            }
            if (uin != null)
            {
                uin.close();
            }
            if (uout != null) 
            {
                uout.close();
            }
        }
        catch(Exception e)
        {
            Toast.makeText(context, "AccessPC Upload Task failed "+e, Toast.LENGTH_LONG).show();
        }
    }
    void uploadFolder(File ufolder,SmbFile ufoldersmb)
    {
        try 
        {
            SmbFile tempSmb=new SmbFile(ufoldersmb.getPath()+ufolder.getName()+"/",auth);
            if(!tempSmb.exists())
            {
                tempSmb.mkdir();
            }
            File[] ftemp=ufolder.listFiles();
            if(ftemp.length==0)
            {
                setupstate(2);
                return;
            }
            for(File m:ftemp)
            {
                if(m.isFile())
                {
                    uploadFile(m,tempSmb);
                }
                else
                {
                    uploadFolder(m,tempSmb);
                }
            }
        } 
        catch (Exception e) 
        {
            Toast.makeText(context, "AccessPC Upload Task failed "+e,Toast.LENGTH_LONG).show();
        }
    }
    void downloadTask()
    {
        Toast.makeText(context, "AccessPC download task "+tasknumber+" Started", Toast.LENGTH_LONG).show();
        try 
        {
            for(SmbFile m:smbArray)
            {
                if(m.isFile())
                {       
                    setdfile(m);
                    setdfilepath(ext+m.getName());
                    downloadFile(dfile,dfilepath);
                }
                else
                {
                    setdfolder(m);
                    setdfolderpath(ext);
                    downloadFolder(dfolder,dfolderpath);
                }
            } 
            setdownstate(2);
        }
        catch (Exception e) 
        {
            Toast.makeText(context,"Download error "+e,Toast.LENGTH_LONG).show();
        }
    }   
    @Override
    protected void onPostExecute(Void result) 
    {
        if(upstate==2)
        {
            setupstate(0);
            Toast.makeText(context, "AccessPC "+taskname+" task "+tasknumber+" Finished", Toast.LENGTH_LONG).show();
        }
        if(downstate==2)
        {
            setdownstate(0);
            Toast.makeText(context, "AccessPC "+taskname+" task "+tasknumber+" Finished", Toast.LENGTH_LONG).show();
        }   
    }
}

这是我的选项菜单。我用它做了我的asyn任务 我在我的主要活动中使用的变量有助于完成这项任务:

String extStorage=Environment.getExternalStorageDirectory()+"/t/";
ArrayList<Helper> helpobject=new ArrayList<Helper>();
int uptask=0;
int downtask=0;
public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch(item.getItemId())
        {
            case DOWNLOAD1:
                            MENU_STATE=MENU_DOWNLOAD;
                            map=display_check(current);
                            return true;
            case UPLOAD:
                            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
                            {
                                if(current.getShare()==null)
                                {
                                    Toast.makeText(this,"UPLOAD FAILED",Toast.LENGTH_LONG).show();
                                }
                                else
                                {
                                    File f=new File(extStorage);
                                    Helper help=new Helper();
                                    help.setufolder(f);
                                    help.setufoldersmb(current);
                                    help.setauthentication(auth);
                                    help.setupstate(1);
                                    help.settasknumber(uptask);
                                    uptask++;
                                    help.settaskname("Upload");
                                    help.setcontext(this.getApplicationContext());
                                    help.execute(1);
                                }
                            }
                            else
                            {
                                Toast.makeText(this,"UPLOAD FAILED--NO SD CARD FOUND",Toast.LENGTH_LONG).show();
                            }
                            return true;
        case DELETE1:
                            MENU_STATE=MENU_DELETE;
                            map=display_check(current);
                            return true;
        case QUIT:
                            int x=0;
                            for(Helper k:helpobject)
                            {
                                if(k.getStatus().equals(AsyncTask.Status.RUNNING)||k.getStatus().equals(AsyncTask.Status.RUNNING))
                                {
                                    Toast.makeText(k.getcontext(), "AccessPC "+k.gettaskname()+" "+k.gettasknumber()+" Cancelled", Toast.LENGTH_SHORT).show();
                                    k.cancel(true);
                                }
                                helpobject.remove(x);
                                x++;
                            }
                            return true;
        case DOWNLOAD2:  
                            if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
                            {
                                int tempcount=0;
                                for(int i=0;i<object.getCount();i++)
                                {
                                    if(object.getter(i)==true)
                                    {
                                        tempcount++;
                                    }
                                }
                                if(tempcount==0)
                                {
                                    Toast.makeText(this,"Please choose atleast one item for download!!",Toast.LENGTH_LONG).show();
                                }
                                else
                                {
                                    Helper help=new Helper();
                                    helpobject.add(help);
                                    help.settasknumber(downtask);
                                    downtask++;
                                    help.settaskname("Download");
                                    help.setcontext(this.getApplicationContext());
                                    help.setextstorage(extStorage);
                                    help.setdownstate(1);
                                    for(int i=0;i<object.getCount();i++)
                                    {
                                        if(object.getter(i)==true)
                                        {
                                            help.setarraysmb(map.get(object.getItem(i)));
                                        }
                                    }
                                    help.execute(0);
                                }
                            }
                            else
                            {
                                Toast.makeText(this,"DOWNLOAD FAILED--NO SD CARD FOUND",Toast.LENGTH_LONG).show();
                            }                   
                            return true;
        case DELETE2:
                            for(int i=0;i<object.getCount();i++)
                            {
                                if(object.getter(i)==true)
                                {
                                    try 
                                    {
                                        map.get(object.getItem(i)).delete();
                                    } 
                                    catch (Exception e) 
                                    {
                                        Toast.makeText(this,"cannot be deleted "+e,Toast.LENGTH_LONG).show();
                                    }
                                }
                            }
                            return true;
        case CANCEL:
                            MENU_STATE=MENU_GENERAL;
                            map=display(current);
                            return true;
        case FINISH:
                            finish();
        default:
                            return super.onOptionsItemSelected(item);
        }
    }

嗨,当我试图显示吐司时,如下面的评论中所述,我得到了相同的异常。请查看下面的代码,我曾经在我的异步任务中显示Toast:

(new Activity()).runOnUiThread(new Runnable(){@Override public void run() {//Your Toast
            Toast.makeText(context, "AccessPC Download Task failed ",Toast.LENGTH_LONG).show();
            }});

我是否需要对异步任务代码或选项菜单代码进行任何更改?

我使用了这样的处理程序:

public Handler handler = new Handler() {
    public void handleMessage(Message msg) 
    {
        Bundle b = msg.getData();
        String key = b.getString(null);
        Toast.makeText(getApplicationContext(),key, Toast.LENGTH_SHORT).show();
    }
};

我正在调用这样的处理程序:

Message msg = new Message();
Bundle b = new Bundle();
b.putString(null, "AccessPC "+taskname+" task "+tasknumber+" Finished");
msg.setData(b);
//this is error
t.handler.sendMessage(msg);

但是如何调用非静态方法?我是否需要为主类创建一个对象(类t扩展列表活动)?

嗨,请查看我从上面的异步任务和菜单发布的选项菜单中选择“退出”操作时获得的另一个例外。如何避免这种异常:

05-07 16:24:07.573: E/AndroidRuntime(13466): FATAL EXCEPTION: main
05-07 16:24:07.573: E/AndroidRuntime(13466): java.util.ConcurrentModificationException
05-07 16:24:07.573: E/AndroidRuntime(13466):    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.test.t.onOptionsItemSelected(t.java:622)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.app.Activity.onMenuItemSelected(Activity.java:2205)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java:748)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:143)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:855)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.view.menu.IconMenuView.invokeItem(IconMenuView.java:532)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.view.menu.IconMenuItemView.performClick(IconMenuItemView.java:122)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.view.View$PerformClick.run(View.java:9080)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.os.Handler.handleCallback(Handler.java:587)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.os.Handler.dispatchMessage(Handler.java:92)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.os.Looper.loop(Looper.java:123)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at android.app.ActivityThread.main(ActivityThread.java:3683)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at java.lang.reflect.Method.invokeNative(Native Method)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at java.lang.reflect.Method.invoke(Method.java:507)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-07 16:24:07.573: E/AndroidRuntime(13466):    at dalvik.system.NativeStart.main(Native Method)

3 个答案:

答案 0 :(得分:3)

Can't create handler inside thread that has not called Looper.prepare(),错误信息相当简单。

您在Handler(后台线程)中创建了一个AsyncTask.doInBackground()对象,该对象需要该线程中的消息泵,即Looper.prepare()

我认为将您的Handler对象的创建从AysncTask中移出到UI线程可能更容易。

以下是OP编辑他/她的问题后的编辑

Toast.makeText(context, "AccessPC Upload task "+tasknumber+" Started", Toast.LENGTH_LONG).show();

上面的行根本不允许在后台线程中显示Toast消息更新 UI ,这必须发生在UI线程中。

再次编辑

您可以使用在UI线程中创建的Handler来发送消息,并在处理程序中通过显示所需的Toast消息来处理该消息。

再次编辑2

private final static int TOAST_MSG_ID_1 = 1;
private final static int TOAST_MSG_ID_2 = 2;
private final static int TOAST_MSG_ID_3 = 3;
// declare a Handler as an instance variable
Handler msgHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
            switch(msg.what()) {
                case TOAST_MSG_ID_1:
                    Toast.makeText(...msg1...).show();
                break;
                case TOAST_MSG_ID_2:
                    Toast.makeText(...msg2...).show();
                break;
                .... other messages follow....
            }
    }
};

// and you will use the following to show a Toast message:
msgHandler.sendEmptyMessage(TOAST_MSG_ID_1);
msgHandler.sendEmptyMessage(TOAST_MSG_ID_2);
msgHandler.sendEmptyMessage(TOAST_MSG_ID_3);
...

有关Handler的更多信息,请先查看javadoc。而google会为你带来更多。

答案 1 :(得分:1)

如下所示写Toast消息我希望它能正常工作。

getApplicationContext().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                       //Your Toast 

                    }
                });

答案 2 :(得分:0)

评论您使用非UI线程显示的所有Toast消息。我认为这个问题..