首页 > 解决方案 > 在调用 onPause() 后,如何停止在后台 android 中循环的异步任务?

问题描述

我正在使用包 com.hierynomus.smbj.share;通过 smb2 连接到网络位置以检查其连接性,但这仅在我的活动开始时运行(在后台)。

一旦调用活动中的侦听器(我从中调用任务),我添加了一个侦听器以在任务返回字符串值(失败,成功)后返回,然后创建连接状态的新实例(此循环它)

这就是我在活动的 onCreate() 处检查连接的方式

//Global ConnectionStatus connectionStatus;

        connectionStatus = new ConnectionStatus();
        connectionStatus.setContext(this);
        connectionStatus.setListener(this);
        connectionStatus.setCon(databaseReadWrite.getMydbc());
        connectionStatus.execute("CheckDatabase", "nodelay");

这就是我在打开另一个活动时尝试取消任务的方式

  protected void onPause() {
        delay.equals("cancel");
        super.onPause();
        MyApplication.activityPaused();
        if (connectionStatus != null) {
            connectionStatus.cancel(true);

        }
        hasRun = false;

    }

然后在异步任务完成后在同一个活动中运行,所以我重新运行了一个新的 connectionStatus 实例

@Override
    public void onTaskCompleted(String result) {
            ActionBar actionBar = this.getSupportActionBar();
            String title = getTitle().toString();
            String code = handlingFunctions.getResultCode(result);
            if (code.equals("1")) {
                Message.message(this, " Database connected to server!");
                setTitle(title + result);
            } else if (code.equals("2")) {
                actionBar.setBackgroundDrawable(new ColorDrawable(Color.RED));
                alertDialog.message(this, result);
            } else if (code.equals("0")) {
                actionBar.setBackgroundDrawable(new ColorDrawable(Color.RED));
                setTitle(title + " Database connected in offline mode");
                alertDialog.message(this, result);
            } else if (code.equals("3")) {
                //alertDialog.message(this, result);
                imageStatus.setText(result);
            } else if (code.equals("4")) {
                imageStatus.setText(result);
            }
            connectionStatus = new ConnectionStatus();
            connectionStatus.setContext(getApplicationContext());
            connectionStatus.setListener(AllParts.this);
            connectionStatus.setCon(databaseReadWrite.getMydbc());
            connectionStatus.execute("CheckDatabase", "delay");

        }
    }



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

    private OnConnectionStatusComplete listener;
    private ArrayList<String> imageNames;
    private ArrayList<ImageDetails> currentImageDetails;
    private SQLiteConnection sqLiteConnection;
    private Context context;

    public void setListener(OnConnectionStatusComplete listen) {
        this.listener = listen;
    }

    public void setImageNames(ArrayList<String> ImageNames) {
        this.imageNames = ImageNames;
    }

    public void setCurrentDetails(ArrayList<ImageDetails> details) {
        this.currentImageDetails = details;
    }

    @Override
    protected void onPostExecute(String s) {
        listener.onTaskCompleted(s);
    }

    public void setContext(Context mContext) {
        context = mContext;
    }

    public void setCon(SQLiteConnection sqlite) {
        sqLiteConnection = sqlite;
    }

     @Override
    protected String doInBackground(String... strings) {
         if(this.isCancelled()){
        return "";
    }else{

                MyApplication myApplication = (MyApplication) context.getApplicationContext();
                String IPAddress = myApplication.getIpaddress();
                String domain = myApplication.getDomainname();
                String username = myApplication.getUsername();
                String password = myApplication.getPassword();
                String containingFolder = myApplication.getSharefolder();
                String temp = "";

                //return null;

                if (strings[1].equals("delay")) {
                    try {
                        Thread.sleep(6000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (strings[0].equals("CheckDatabase")) {
                    temp = checkDatabaseConnect();
                } else {
                    temp = checkImageConnection(IPAddress, domain, username, password, containingFolder);
                }
                return temp;
            }


    }

String checkDatabaseConnect() {
    String statement = "PRAGMA sync_status";
    JSONArray is_ready = new JSONArray();
    try {
        SQLiteStatement mystatement = null;

        try {
            mystatement = sqLiteConnection.prepareStatement(statement);
        } catch (SQLException ex) {
            try {

                java.io.File path = new java.io.File("/sdcard/exports/logs");
                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                String currentDateTime = dateFormat.format(new Date()) + " ";
                java.io.File myFile = new java.io.File(path, "DBCrashes.txt");
                FileOutputStream fOut = new FileOutputStream(myFile, true);
                OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
                myOutWriter.append("\n" +
                        "\r");
                myOutWriter.append(currentDateTime + "Get pragma results: (" + statement + ")" + ex);
                myOutWriter.close();
                fOut.close();
            } catch (java.io.IOException e) {
                //do something if an IOException occurs.
            }

        }
        mystatement.step();
        int ncols = mystatement.getColumnCount();

        if (ncols > 0) {
            String result = mystatement.getColumnTextNativeString(0);
            JSONObject jObject = new JSONObject(result);
            is_ready = jObject.getJSONArray("peers");
            if (is_ready.length() > 0) {
                return "Success, Database is connected! (1)";
            } else {
                return "The database is not connected to the server. In offline mode, check network and restart application to connect to server. (0)";

            }
        }
        mystatement.dispose();

    } catch (SQLException ex) {
        try {

            java.io.File path = new java.io.File("/sdcard/exports/logs");
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
            String currentDateTime = dateFormat.format(new Date()) + " ";
            java.io.File myFile = new java.io.File(path, "DBCrashes.txt");
            FileOutputStream fOut = new FileOutputStream(myFile, true);
            OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
            myOutWriter.append("\n" +
                    "\r");
            myOutWriter.append(currentDateTime + " (" + statement + ")" + ex);
            myOutWriter.close();
            fOut.close();
            return "No connection to a database, please try again (2)";
        } catch (java.io.IOException e) {

            //do something if an IOException occurs.

        }

    } catch (JSONException e) {
        e.printStackTrace();
    }

    return "Success (5)";

}
}

我遇到的问题是在我离开活动后,任务仍在运行并返回此错误(我知道这是因为它考虑了延迟)

标签: androidandroid-asynctasksmbj

解决方案


您确实已经实现了对 isCanceled 的处理,但这个实现只是在开始。

您当前的流程是这样的:

  1. 任务开始,立即检查它是否被取消(因为它是 doInBackground 中的第一行)
  2. onPause 被调用,任务的取消被调用
  3. 由于已经进行了取消检查,您的任务将继续自由运行

你如何解决这个问题?

最简单的方法是在调用 checkDatabaseConnection 或 checkImageConnection 之前检查它是否被取消。甚至在这些方法中检查它是否被取消。

即使正确完成,您的 Thread.sleep 也可能导致您的 AsyncTask 在调用 onPause 后 6 秒被取消。

由于这样的原因,不再使用 AsyncTask。线程还有其他更好的选择。

这个 或这个会给你一个起点。


推荐阅读