如何在调用onPause()之后停止在后台android中循环的异步任务?

时间:2019-02-10 12:19:57

标签: android android-asynctask smbj

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

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

这是我在活动的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)";

}
}

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

2 个答案:

答案 0 :(得分:1)

您确实实现了isCanceled的处理,但是此实现只是开始。

您的当前流量是这样的:

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

您如何解决此问题?

最简单的方法是在调用checkDatabaseConnection或checkImageConnection之前检查它是否已取消。甚至在那些方法内部,也检查它是否被取消。

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

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

This or this将为您提供一个起点。

答案 1 :(得分:0)

尝试检查在Thread.sleep(6000)之后是否取消了任务,因此,即使在调用cancel时任务处于睡眠状态,完成后仍会返回。

if (strings[1].equals("delay")) {
   try {
      Thread.sleep(6000);
      if(this.isCancelled()) {
          return "";
      }
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   /*if(this.isCancelled()) {
      return "";
   }*/
}