【发布时间】:2015-09-05 16:26:33
【问题描述】:
我遇到了一起调用 runOnuiThread 和 AsyncTask 的问题。
我的 AsynchTask 通过 runOnUIThread 调用获取数据以填充 listView。 即使 UI 不在焦点上,此 Asych 任务也可以获取数据。它从 UI 屏幕开始并一直运行,直到应用程序被注销。 现在来自此任务的数据只能填充特定的列表视图。 现在,如果我使用对 AsynchTask 的调用 executeOnExecutor 调用从另一个视图调用另一个异步任务,则异步任务不会运行到强制执行。它锁定了。 如果我注释掉名为 Receiver.. 的永无止境的 AsychTask 的代码,那么所有 UI 的列表视图都会被填充,并且没有 Asych Task 锁定。 此 Receiver 等待 REST API 调用以返回响应,但由于我正在通过 executeonExecutor 调用运行,因此它应该是并行处理。 我需要让接收器一直运行,因为这是我的应用程序不可或缺的一部分。 我可以在这里使用什么策略来解决这个问题。 这是我的代码 sn-ps。
public class Receiver {
private final static String QUEUE_NAME = "hello";
private String m_ErrorMessage;
private IRunOnUIThreadCallback iRunOnUIThreadCallback;
private Send m_Received;
private int m_TimeoutDuration;//how long the reading of new message waits in milli seconds
public void SetCallback(IRunOnUIThreadCallback runOnUIThreadCallback)
{
iRunOnUIThreadCallback = runOnUIThreadCallback;
}
public void SetTimeoutDuration(int timeout)
{
m_TimeoutDuration = timeout;
}
public void StartReceiver(Send receiverInfo)
{
String receivedInfo = null;
try {
new ReceiveInfo ().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, receiverInfo);
}
catch(Exception exp)
{
m_ErrorMessage = exp.getMessage();
}
}
private class ReceiveInfo extends AsyncTask<Send, Void, Send>
{
//initiate vars
public receive() {
super();
//my params here
}
protected Message doInBackground(Send... receiverInfo)
{
Send recv=null;
try {
PreferenceSingleton single = PreferenceSingleton.getInstance();
final User user = single.getUser();
final SvcApi svc = LoginAuthSvc.init();
Send send=(Send)receiverInfo[0];
send.setUserId(user.getUsername());
//dxbrem
while (true) {
recv=svc.receive(send);
String str= recv.get();
if ((str == null || (str.trim().length() == 0))) {
continue;
}
//DJ uncomment
iRunOnUIThreadCallback.RunAfterIsReceived(recv);
//messages.add(message);
System.out.println(" [x] Received '" + recv + "'");
}
}catch(Exception exp)
{
m_ErrorMessage = exp.getMessage();
}
return recv;
}
}
public String getErrorMessage() {
return m_ErrorMessage;
}
}
public interface IRunOnUIThreadCallback {
public void RunAfterIsReceived(ByteSent m);
public void RunAfterIsReceived(Send m);
}
处理这个的类..有以下代码和
public class MainFragment extends Fragment implements MFragment.OnFragmentInteractionListener, IRunOnUIThreadCallback {
private Receiver mReceiver;
public void SetUICallbackOnMessageReceiver()
{
mReceiver.SetCallback(this);
}
private void callRunUIThread(final SentInfo m) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
if (m!= null) {
mGridArray.add(message);
if (mListAdapter != null) {
mListAdapter.notifyDataSetChanged();
mListView.setSelection(mListAdapter.getCount());
mListView.smoothScrollToPosition(mListAdapter.getCount());
}
}
}
}); // end of runOnUiThread
}
@Override
public void RunAfterIsReceived(ByteSent m) {
}
@Override
public void RunAfterIsReceived(Sent m) {
SentInfo m= new SentInfo(false, recv.getInfo());
callRunUIThread(msg);
}
mListAdapter 是 ListAdapter mListView 是 ListView
这里是异步任务代码
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
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,Activity activity, TaskCallback<V> callback){
new CallableTask<V>(activity,call, callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR );
}
private Callable<T> callable_;
private AsyncTask<Void, Void, String> asyncTask_;
private Context context;
private Activity activity;
private Fragment fragmentActivity;
private android.support.v4.app.Fragment dynamicFragment;
private TaskCallback<T> callback_;
private Exception error_;
public CallableTask(Fragment actvy,Callable<T> callable, TaskCallback<T> callback) {
callable_ = callable;
callback_ = callback;
fragmentActivity=actvy;
}
public CallableTask(Activity actvy,Callable<T> callable, TaskCallback<T> callback) {
callable_ = callable;
callback_ = callback;
activity=actvy;
}
@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,activity);
}
}
public static <V> void invoke(Callable<V> call, Fragment _frg, TaskCallback<V> callback) {
new CallableTask<V>(_frg,call, callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR );
}
// public CallableTask(android.support.v4.app.Fragment chatActivity,Callable<T> callable, TaskCallback<T> callback) {
// callable_ = callable;
// callback_ = callback;
// dynamicFragment=chatActivity;
// }
public CallableTask(android.support.v4.app.Fragment actvy,Callable<T> callable, TaskCallback<T> callback) {
callable_ = callable;
callback_ = callback;
dynamicFragment=actvy;
}
public static <V> void invoke(Callable<V> call, android.support.v4.app.Fragment _frg, TaskCallback<V> callback) {
new CallableTask<V>(_frg,call, callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR );
}
}
这里会调用它...仅在单击按钮发送时调用。
CallableTask.invoke(new Callable<Sent>() {
@Override
public Sent call() throws Exception {
}, this, new TaskCallback<Sent>() {
@Override
public void success(Sent result, Context context) {
mGridArray.add(result);
if (mListAdapter != null) {
mListAdapter.notifyDataSetChanged();
mListView.setSelection(mListAdapter.getCount());
mListView.smoothScrollToPosition(mListAdapter.getCount());
}
@Override
public void error(Exception e) {
}
});
谢谢 迪伦
【问题讨论】:
-
对于长时间运行的任务,Service 不是比 AsyncTask 更好的选择吗?
-
我正在阅读有关服务的信息,但我不明白如何为长时间运行的任务连接服务以及如何填充 UI?尤其是当我离开 UI ListView 并移至另一个。
-
如果那个 ListView 不再出现在屏幕上,就没有什么可更新的了,对吧?
-
我终于解决了这个问题,方法是从启动该线程的活动片段中对线程运行 Asynch.cancel 调用。当我远离活动时。如果我没有,它会阻止任何其他任务运行,
标签: android android-listview android-asynctask