需要更多地了解Android中的AsyncTask

时间:2012-10-24 04:22:45

标签: android android-asynctask

我有这行代码完全没有问题,唯一的问题是,每次执行此代码时,应用程序都会等待所有进程完成,使界面无法响应半秒钟。我找到的最佳解决方案是使用Thread,但它会导致一些问题,所以我诉诸AsyncTask我无法理解。任何人都可以帮助我如何将其实现到这行代码中吗?

            ima.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    search.clearFocus();
                    currentItem = ssil;
                    if (currentRoom.equals("None")) {
                        Toast.makeText(StartMoving.this, "Please select a room before adding an item", Toast.LENGTH_LONG).show();
                    }else{

                        try {
                            String currentitemholder = startmoving.getSingleItemName(currentMove, currentRoom, currentItem);
                            if (currentitemholder.equals(currentItem)) {
                                String ssi = startmoving.getSingleItemValue(currentMove, currentRoom, currentItem);
                                String ssiw = startmoving.getSingleItemWeight(currentMove, currentRoom, currentItem);
                                String stw = startmoving.getTotalWeight(currentMove);
                                String srw = startmoving.getRoomWeight(currentMove, currentRoom);
                                String diw = startmoving.getListItemWeight(currentItem);
                                int istw = Integer.parseInt(stw);
                                int isiw = Integer.parseInt(ssiw);
                                int isi = Integer.parseInt(ssi);
                                int isrw = Integer.parseInt(srw);
                                int idiw = Integer.parseInt(diw);
                                currentItemValue = "" + ++isi;
                                currentItemWeight = "" + (isiw + idiw);
                                currentTotalItemWeight = "" + (istw + idiw);
                                currentRoomWeight = "" + (isrw + idiw);
                                currentTotalItem = startmoving.getTotalItem(currentMove) + 1; 
                                startmoving.updateItems(currentMove, currentRoom, currentItem, currentItemValue, currentItemWeight);
                                startmoving.setMoveWeight(currentTotalItemWeight, currentMove);
                                startmoving.setRoomWeight(currentRoomWeight, currentMove, currentRoom); 
                                startmoving.setTotalItem(currentMove, currentTotalItem);
                                String displayname = startmoving.getItemName(currentMove, currentRoom);
                                String displayvalue = startmoving.getItemValue(currentMove, currentRoom);
                                String displayweight = startmoving.getItemWeightLBS(currentMove, currentRoom);
                                String displaytotalweight = startmoving.getTotalWeightLBS(currentMove);
                                String displayroomweight = startmoving.getRoomWeightLBS(currentMove, currentRoom);
                                roomContent.setText(displayname);
                                itemValue.setText(displayvalue);
                                itemWeight.setText(displayweight);
                                totalweight.setText(displaytotalweight);
                                roomweight.setText(displayroomweight); 
                                int displaytotalitem = startmoving.getTotalItem(currentMove); 
                                totalitem.setText("" + displaytotalitem);
                            }
                        }catch (Exception e) {
                            // TODO Auto-generated catch block
                            currentItemValue = "1";
                            currentItemWeight = ssiw;
                            String stw = startmoving.getTotalWeight(currentMove);
                            String srw = startmoving.getRoomWeight(currentMove, currentRoom);
                            String diw = startmoving.getListItemWeight(currentItem);
                            int istw = Integer.parseInt(stw);
                            int isrw = Integer.parseInt(srw);
                            int idiw = Integer.parseInt(diw);
                            currentTotalItemWeight = "" + (istw + idiw);
                            currentRoomWeight = "" + (isrw + idiw);
                            currentTotalItem = startmoving.getTotalItem(currentMove) + 1; 
                            startmoving.addNewItems(currentMove, currentRoom, currentItem, currentItemValue, currentItemWeight);
                            startmoving.setMoveWeight(currentTotalItemWeight, currentMove);
                            startmoving.setRoomWeight(currentRoomWeight, currentMove, currentRoom); 
                            startmoving.setTotalItem(currentMove, currentTotalItem);
                            startmoving.setTotalItem(currentMove, currentTotalItem);
                            String displayname = startmoving.getItemName(currentMove, currentRoom);
                            String displayvalue = startmoving.getItemValue(currentMove, currentRoom);
                            String displayweight = startmoving.getItemWeightLBS(currentMove, currentRoom);
                            String displaytotalweight = startmoving.getTotalWeightLBS(currentMove);
                            String displayroomweight = startmoving.getRoomWeightLBS(currentMove, currentRoom);
                            roomContent.setText(displayname);
                            itemValue.setText(displayvalue);
                            itemWeight.setText(displayweight);
                            totalweight.setText(displaytotalweight);
                            roomweight.setText(displayroomweight); 
                            int displaytotalitem = startmoving.getTotalItem(currentMove); 
                            totalitem.setText("" + displaytotalitem);
                        }
                    }
                }
            });

            imr.setOnClickListener(new OnClickListener() {

                @SuppressLint("ShowToast")
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    search.clearFocus();
                    currentItem = ssil;
                    if (currentRoom.equals("None")) {
                        Toast.makeText(StartMoving.this, "Please select a room before removing an item", Toast.LENGTH_LONG).show();
                    }else{

                        try {
                            String currentitemholder = startmoving.getSingleItemName(currentMove, currentRoom, currentItem);
                            if (currentitemholder.equals(currentItem)) {
                                String ssi = startmoving.getSingleItemValue(currentMove, currentRoom, currentItem);
                                String ssiw = startmoving.getSingleItemWeight(currentMove, currentRoom, currentItem);
                                String stw = startmoving.getTotalWeight(currentMove);
                                String srw = startmoving.getRoomWeight(currentMove, currentRoom);
                                String diw = startmoving.getListItemWeight(currentItem);
                                int istw = Integer.parseInt(stw);
                                int isiw = Integer.parseInt(ssiw);
                                int isi = Integer.parseInt(ssi);
                                int isrw = Integer.parseInt(srw);
                                int idiw = Integer.parseInt(diw);
                                if (isi > 1) {
                                    currentItemValue = "" + --isi;
                                    currentItemWeight = "" + (isiw - idiw);
                                    currentTotalItemWeight = "" + (istw - idiw);
                                    currentRoomWeight = "" + (isrw - idiw);
                                    currentTotalItem = startmoving.getTotalItem(currentMove) - 1; 
                                    startmoving.updateItems(currentMove, currentRoom, currentItem, currentItemValue, currentItemWeight);
                                    startmoving.setMoveWeight(currentTotalItemWeight, currentMove);
                                    startmoving.setRoomWeight(currentRoomWeight, currentMove, currentRoom); 
                                    startmoving.setTotalItem(currentMove, currentTotalItem);
                                    startmoving.setTotalItem(currentMove, currentTotalItem);
                                    String displayname = startmoving.getItemName(currentMove, currentRoom);
                                    String displayvalue = startmoving.getItemValue(currentMove, currentRoom);
                                    String displayweight = startmoving.getItemWeightLBS(currentMove, currentRoom);
                                    String displaytotalweight = startmoving.getTotalWeightLBS(currentMove);
                                    String displayroomweight = startmoving.getRoomWeightLBS(currentMove, currentRoom);
                                    roomContent.setText(displayname);
                                    itemValue.setText(displayvalue);
                                    itemWeight.setText(displayweight);
                                    totalweight.setText(displaytotalweight);
                                    roomweight.setText(displayroomweight); 
                                    int displaytotalitem = startmoving.getTotalItem(currentMove); totalitem.setText("" + displaytotalitem);
                                }else{
                                    String sstw = startmoving.getTotalWeight(currentMove);
                                    String ssrw = startmoving.getRoomWeight(currentMove, currentRoom);
                                    int isstw = Integer.parseInt(sstw);
                                    int issrw = Integer.parseInt(ssrw);
                                    currentTotalItemWeight = "" + (isstw - idiw);
                                    currentRoomWeight = "" + (issrw - idiw);
                                    currentTotalItem = startmoving.getTotalItem(currentMove) - 1; startmoving.setMoveWeight(currentTotalItemWeight, currentMove);
                                    startmoving.setRoomWeight(currentRoomWeight, currentMove, currentRoom);
                                    startmoving.deleteItem(currentMove, currentRoom, currentItem); startmoving.setTotalItem(currentMove, currentTotalItem);
                                    startmoving.setTotalItem(currentMove, currentTotalItem);
                                    String displayname = startmoving.getItemName(currentMove, currentRoom);
                                    String displayvalue = startmoving.getItemValue(currentMove, currentRoom);
                                    String displayweight = startmoving.getItemWeightLBS(currentMove, currentRoom);
                                    String displaytotalweight = startmoving.getTotalWeightLBS(currentMove);
                                    String displayroomweight = startmoving.getRoomWeightLBS(currentMove, currentRoom);
                                    roomContent.setText(displayname);
                                    itemValue.setText(displayvalue);
                                    itemWeight.setText(displayweight);
                                    totalweight.setText(displaytotalweight);
                                    roomweight.setText(displayroomweight); 
                                    int displaytotalitem = startmoving.getTotalItem(currentMove); 
                                    totalitem.setText("" + displaytotalitem);
                                }   
                            }
                        }catch (Exception e) {
                            // TODO Auto-generated catch block

                        }
                    }
                }
            });

正如您所看到的,这两个按钮调用数据库(发送和接收数据)并将其显示到GUI。

修改

感谢你们的精彩回应!在我决定正确的答案之前,我会先学习AsyncTask。仍然需要处理你给我的所有这些信息。

修改 忘了提起startmoving是我的数据库模块

4 个答案:

答案 0 :(得分:2)

如果您执行持久的操作,例如加载文件或访问数据,Android应用程序的用户界面将阻止,直到相应的代码完成。

AsyncTask

为了使用AsyncTask类,您必须扩展它并至少覆盖doInBackground()方法。

您需要实施的最常见方法是:

   1. onPreExecute() – called on the UI thread before the thread starts running. This method is usually used to setup the task, for example by displaying a progress bar.

   2. doInBackground(Params…) – this is the method that runs on the background thread. In this method you should put all the code you want the application to perform in background. Referring to our Simple RSS Aplication, you would put here the code that downloads the XML feed and does the parsing. The doInBackground() is called immediately after onPreExecute(). When it finishes, it sends the result to the onPostExecute().

   3. onProgressUpdate() - called when you invoke publishProgress() in the doInBackground().

   4. onPostExecute(Result) – called on the UI thread after the background thread finishes. It takes as parameter the result received from doInBackground().

现在在您的代码选择中,您可以做什么。

所有数据库操作和数据操作代码均以doInBackground(Params…)方式编写,并以onPostExecute(Result)方法显示数据。

感谢。

答案 1 :(得分:1)

AsyncTask 执行另一个线程内doInBackground()内的所有内容,该线程无权访问您的视图所在的GUI。

preExecute()postExecute()允许您在此新线程中发生繁重操作之前和之后访问GUI,您甚至可以将长操作的结果传递给postExecute()然后显示任何处理结果。

Android通过一个线程修改用户界面,即所谓的UI线程。如果直接在UI线程上执行长时间运行操作,例如从Internet下载文件,应用程序的用户界面将“冻结”,直到相应的任务完成。当发生这种情况时,用户很容易将您的应用程序视为缓慢。

AsyncTask可以正确,轻松地使用UI线程。此类允许执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序。

  1. onPreExecute() - 在线程开始运行之前调用UI线程。此方法通常用于设置任务,例如通过显示进度条。

  2. doInBackground(Params…) - 这是在后台线程上运行的方法。在此方法中,您应该将您希望应用程序在后台执行的所有代码。参考我们的简单RSS应用程序,您可以在此处输入下载XML提要并进行解析的代码。在onPreExecute()之后立即调用doInBackground()。完成后,它会将结果发送到onPostExecute()。

  3. onProgressUpdate() - 在doInBackground()中调用publishProgress()时调用。

  4. onPostExecute(Result) - 在后台线程完成后调用UI线程。它将从doInBackground()收到的结果作为参数。

  5. AsyncTask是一个泛型类,它使用3种类型:AsyncTask。

    Params – the input. what you pass to the AsyncTask
    Progress – if you have any updates, passed to onProgressUpdate()
    Result – the output. what returns doInBackground()
    

    创建任务后,可以像这样执行:

    new DownloadTast().execute(url1, url2, urln);
    

    Here is one example of AsyncTask

答案 2 :(得分:1)

好的,如果你没有给出解决方案,我认为最好开始阅读Android中的异步请求:http://developer.android.com/reference/android/os/AsyncTask.html。了解Web的异步特性将有助于您了解UI与可能呈现的数据的分离。

响应能力是您希望将UI与数据分开的首要原因。对于使用EDT(事件路径线程)的Java Swing开发人员来说,这可能是最好的解释:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html。有很多慢速应用程序的例子,开发人员会将长时间运行的进程附加到他们的按钮或其他任何东西,然后尝试通过使用他们自己的线程来加速处理。 Swing最终使用SwingWorker和doInBackground()在Java 6中修复了这个问题。对于转向Android的Swing开发人员,他们可能会看看AsyncTask并问,为什么在Java中不那么简单?

因此,请花一些时间熟悉AsyncTask,了解如何使用它,如何将它与Listener结合使用以获得更大的灵活性,然后您将了解如何更改代码。

如果您需要更多帮助指向正确的方向,请告诉我们。

答案 3 :(得分:1)

基本上,您需要扩展AsyncTask类并进行自己的实现。您可以利用doInBackground()函数在非UI线程中运行的事实,并且它返回的结果可以在UI线程中运行的onPostExecute()函数中使用。

你提到你的代码调用了一个数据库,所以我假设你的“startmoving”对象是数据库模块。我将在下面的示例代码中将其称为MovingDb类,因为在代码中未显示实际的类名称。

// this will hold all your calculated value
private class DisplayInfo {
   String displayName, displayValue, displayWeight, displayTotalWeight, displayRoomWeight;
   int displayTotalItem;
}

private class ItemHolderTask extends AsyncTask<MovingDb, Integer, DisplayInfo> {

   protected DisplayInfo doInBackground(MovingDb... movingDbs) {
      // this code runs in background thread so do your DB work here
      if (movingDbs != null && movingDbs.length > 0 && movingDbs[0] != null) {
         MovingDb startMoving = movingDbs[0];
         // move all your db operations here
         String currentItemHolder = startMoving.getSingleIteName(....)
         // blah blah
         DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.displayName = startMoving.getItemName(...);
         displayInfo.displayValue = startMoving.getItemValue(...);
         // set up the rest of your display info values
         return displayInfo;
      }
   }

   protected void onPostExecute(DisplayInfo displayInfo) {
      // the displayInfo you return from doInBackground comes here
      if (displayInfo != null) {
         roomContent.setText(displayInfo.displayName);
         itemValue.setText(displayInfo.displayValue);
         // and so on...
      }
   }
}

在你的onClick函数中,你将只启动ItemHolderTask:

new ItemHolderTask().execute(startMoving);