优于在AsynTask中使用内部或嵌套类

时间:2018-04-22 02:21:57

标签: java android multithreading android-asynctask swingworker

无论是在Android还是Java中,当我们调用AsyncTaskSwingWorker时,它都可以用作内部或嵌套类。我担心Android设备中的内存泄漏问题。如果您将内部类作为活动参考,则会自动传递。通过采用嵌套类,您必须手动传递活动引用,以便内部/嵌套基本上执行相同的工作。

我遇到的一个问题是活动终止,当AsyncTask结束时,它会破坏应用程序。我知道并使用了无头片段,但是我的问题是关于在Android和Java中使用内部/嵌套类,你推荐哪一个?例如,我在JFrame中执行此任务,当然我想使用执行特定任务的特定类(每个任务一个类)而不是放置内联代码。

new SwingWorker<Void, Void>() {
        private Exception exception = null;

        @Override
        protected Void doInBackground() throws Exception {
            try {
                callback.login();
            } catch(SQLException e) {
                exception = e;
            }

            return null;                
        }

        @Override
        protected void done() {
            if(exception != null) {
                // show fail
            } else {
                update();
            }
        }
    }.execute();
}

2 个答案:

答案 0 :(得分:0)

如果类没有父类没有标识,我会将类作为内部类,并将内部类标记为静态,以避免您提到的问题。

在Android中,您可以传递父活动的Weak reference以避免泄漏,并确保在onStop中取消AsyncTask。一般尽量避免使用AsyncTask。将它用于琐碎的用例。对于主要用例,请依赖Services / IntentService。

从程序员的角度来看,创建内部类并让类访问父类的数据非常方便。但它会导致编译器的一些工作量。内部编译器生成getter方法,并在生成.class文件之前将其添加到代码中。这不是一个好主意,因为它会影响父类的封装

答案 1 :(得分:0)

在Android中,您可以通过interface的实施来处理这种情况。让我们像interface一样,如下所示。

public interface HttpResponseListener {
    void httpResponseReceiver(String result);
}

现在,在Activity通过AsyncTask调用登录功能时,只需将界面从活动类传递给AsyncTask即可。请记住,您的AsyncTask也应该具有该侦听器的实例变量。因此整体实现应如下所示。

public abstract class HttpRequestAsyncTask extends AsyncTask<Void, Void, String> {

    public HttpResponseListener mHttpResponseListener;
    private final Context mContext;

    HttpRequestAsyncTask(Context mContext, HttpResponseListener listener) {
        this.mContext = mContext;
        this.mHttpResponseListener = listener;
    }

    @Override
    protected String doInBackground(Void... params) {
        String result = null;

        try {
            result = login(mContext); // use the context if necessary
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    protected void onPostExecute(final String result) {
        mHttpResponseListener.httpResponseReceiver(result);
    }

    @Override
    protected void onCancelled() {
        mHttpResponseListener.httpResponseReceiver(null);
    }
}

现在您需要在调用httpResponseReceiver中实现Activity功能。所以样本活动应该是这样的。

public class YourActivity extends AppCompatActivity implements HttpResponseListener {
    // ... Other code and overriden functions 

    public void callAsyncTaskForLogin() {
        // Pass the listener here
        HttpRequestAsyncTask loginTask = new HttpRequestGetAsyncTask(
            YourActivity.this, this);
            loginTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    @Override
    public void httpResponseReceiver(String result) {
        // Get the response callback here
        // Do your changes in UI elements here. 
    }
}

这是您可以避免潜在内存泄漏的方法,因为您正在使用活动内部活动的上下文更改UI元素。当后台AsyncTask完成时,它将责任传递给回调函数,并且不保存上下文的引用。

如果应用程序完成,AsyncTask将执行并将引用传递给调用活动,在这种情况下,活动将无法接收。但是,这也不会产生任何内存泄漏。