如何销毁 CallableTask Android

How to destroy a CallableTask Android

我正在开发一个将图像发送到服务器的应用程序。

我有一个带有取消按钮的 ProgressDialog(有时用户想取消发送)。

方法 "postImage" 调用带有 TaskCallBack 的 CallableTask,TaskCallBack 使用 Retrofit 发送电子邮件。

如果用户单击“取消”按钮,我想终止 CallableTask。

我该怎么做?

Activity代码

public  class ListaMenuPrincipalProducao extends ListFragment{

PalmapSvcApi svc;
private int progressBarStatus = 0;
DatabaseManager dbManager;
String[] TextoLista;
// Array of integers points to images stored in /res/drawable/
int[] imagenes;
ListAdapter adapter;
// Array of strings to store currencies
String[] info;
ConnectivityManager mConectivityManager;
int Count_ok=0;
ProgressDialog progressBar;

ProgressDialog  SendingDialog;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    // Each row in the list stores country name, currency and flag
    List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();


    dbManager = new DatabaseManager(getActivity());

    mConectivityManager = (ConnectivityManager) getActivity().getSystemService(MainActivity.CONNECTIVITY_SERVICE);


    return super.onCreateView(inflater, container, savedInstanceState);
}


@Override
public void onResume()
{
    super.onResume();

    svc = PalmapSvc.init(getActivity());

}


@Override
public void onListItemClick(ListView l, View v, int position, long id) {

    else if (position==2)
    {

                    if(mConectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting()) {
                        progressBar = new ProgressDialog(v.getContext());
                        progressBar.setCancelable(false);
                        progressBar.setMessage("Subindo Fotos pro Servidor...");
                        progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                        progressBar.setProgress(0);
                        progressBar.setMax(getImageCount());
                        progressBar.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancelar", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                progressBar.dismiss();
                            }
                        });
                        progressBar.show();

                                }
                            }

                            }
                        }, 30000*getImageCount());

                    }
                   postImage(/* xxx */); 
        }
    }

}
}

public void postImage(final long id, final String ImagePath)
{
    File image = new File(ImagePath);

    final TypedFile typedfile = new TypedFile("image/*",image);

    if (svc != null) {
        CallableTask.invoke(new Callable<String>() {

            @Override
            public String call() throws Exception {
                String g = svc.updateImage(typedfile, id);
                return g;
            }
        }, new TaskCallback<String>() {

            @Override
            public void success(String result) {

                changeImageStatus(ImagePath);
                if(progressBar != null) {
                    progressBar.setProgress(progressBar.getProgress() + 1);
                }  

            }

            @Override
            public void error(Exception e) {
                Toast.makeText(
                        getActivity(),
                        "Erro no envio da Imagem. Tente de novo quando tiver conexão a Internet",
                        Toast.LENGTH_SHORT).show();
                progressBar.dismiss();

            }
        });
     }
boolean isOnline() {
    ConnectivityManager manager = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);

    return manager.getActiveNetworkInfo() != null &&
            manager.getActiveNetworkInfo().isConnectedOrConnecting();
}

CallableTask

public class CallableTask<T> extends AsyncTask<Void,Double,T> {

private static final String TAG = CallableTask.class.getName();

public static <V> void invoke(Callable<V> call, TaskCallback<V> callback){
    new CallableTask<V>(call, callback).execute();
}

private Callable<T> callable_;

private TaskCallback<T> callback_;

private Exception error_;

public CallableTask(Callable<T> callable, TaskCallback<T> callback) {
    callable_ = callable;
    callback_ = callback;
}

@Override
protected T doInBackground(Void... ts) {
    T result = null;
    try{
        result = callable_.call();
    } catch (Exception e){
        Log.e(TAG, "Error invoking callable in AsyncTask callable: "+callable_, e);
        error_ = e;
    }
    return result;
}

@Override
protected void onPostExecute(T r) {
    if(error_ != null){
        callback_.error(error_);
    }
    else {
        callback_.success(r);
    }
}
}

TaskCallback

public interface TaskCallback<T> {

public void success(T result);
public void error(Exception e);
}

如果用户单击“取消”按钮,我如何销毁此 CallableTaskBack?

使用线程中断。只要你不在你的任务中进行不可中断的阻塞调用,你所需要的就是正确处理中断条件,就像这样:

// Uses isInterrupted() to keep interrupted status set
if (Thread.currentThread().isInterrupted()) 
{
    // Cannot use InterruptedException since it's checked
    throw new RuntimeException(); 
}

如果你进行不可中断的阻塞调用(比如网络IO),事情会变得更复杂,你需要以某种方式手动中断它们,例如,通过关闭底层套接字。

这里有完整的解决方案:

How can I make shutdown work properly with this custom ExecutorService?

检查这个 link:

http://ideone.com/AYmuZD