adb error cannot bind to 127.0.0.1:5038:
出现这种情况多半是端口被其他程序占用了,一般是自己电脑的手机助手程序 我们可以打开cmd输入以下命令查看是谁占用了端口 netstat -nao|findstr 5038 32272为pid,我们可以在任务管理器找到这个程序然后kill,在重启Android studio就好了
本文简单介绍Android中的AsyncTask,并从源码角度分析它的流程和特点。
AsyncTask有助于使用UI线程。
这个类能让你不主动使用多线程或Handler,在UI线程进行后台操作并发布结果。
是一个在不用多线程和Handler的情况下的帮助类。AsyncTask适用于短时间的操作(最多几秒)。
如需长时间的线程操作,建议使用多线程包java.util.concurrent中的API,比如Executor,ThreadPoolExecutor 和 FutureTask
AsyncTask任务的构成:
Params, Progress 和 Result onPreExecute, doInBackground, onProgressUpdate 和 onPostExecute 虚构一个计算任务
/**
* 虚拟的计算任务
*/
private class CalculationTask extends AsyncTask<Float, Integer, Float> {
protected Float doInBackground(Float... inputs) {
Log.d(TAG, "doInBackground thread ID = " + Thread.currentThread().getId());
long step = 0;
float result = 0;
for (float f : inputs) {
// 假设这里有一些耗时的操作
result += f;
}
while (step < 5) {
result += step;
step++;
publishProgress((int) step);
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
Log.d(TAG, "onProgressUpdate thread ID = " + Thread.currentThread().getId());
Log.d(TAG, "onProgressUpdate: " + progress[0]);
}
protected void onPostExecute(Float result) {
Log.d(TAG, "onPostExecute thread ID = " + Thread.currentThread().getId());
Log.d(TAG, "任务执行完毕");
}
}
// 执行任务
new CalculationTask().execute(1.2f, 2.3f, 6.3f);
/*
logcat
Main thread ID = 1
doInBackground thread ID = 8089
onProgressUpdate thread ID = 1
onProgressUpdate: 1
...
onProgressUpdate thread ID = 1
onProgressUpdate: 5
onPostExecute thread ID = 1
任务执行完毕
*/
AsyncTask使用的3种泛型
不用的泛型可以用Void表示。例如
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
异步任务执行时经过4个步骤
onPreExecute() UI线程在任务开始前调用这个方法。此方法常用来设置任务,比如在屏幕上显示一个进度条。doInBackground(Params...) onPreExecute()执行完毕后立即在后台线程中执行。这一步用来执行耗时的后台计算。publishProgress(Progress...)通知出去一个或多个进度。这些进度值会被onProgressUpdate(Progress...)在UI线程收到。onProgressUpdate(Progress...) 调用publishProgress(Progress...)后会在UI线程中执行。用来显示执行中任务的UI。onPostExecute(Result) 后台任务执行完毕时被调用。最终结果会被传入这个方法。调用cancel(boolean)可随时取消任务。取消任务后isCancelled()会返回true。
调用这个方法后,后台任务doInBackground(Object[])执行完毕后会调用onCancelled(Object)而不再是onPostExecute(Object)。
为保证任务能被及时地取消,在doInBackground(Object[])中应该经常检查isCancelled()返回值
一些线程规则
execute(Params...) onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) IllegalStateException)。需要解决的问题:
AsyncTask是如何调用后台线程完成任务的?线程是如何调度的?
AsyncTask使用Executor,利用WorkerRunnable和FutureTask来执行后台任务
private final WorkerRunnable<Params, Result> mWorker; // 实现了 Callable
private final FutureTask<Result> mFuture;
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
使用Handler来进行线程调度。内部定义了一个类InternalHandler。
execute(Params... params)方法切入先看方法execute(Params... params),使用默认执行器,并传入参数
调用xecuteOnExecutor(Executor exec, Params... params)
@MainThread // 指定在主线程执行
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
先判断当前状态,如果状态不是Status.PENDING,则抛出异常。
否则进入Status.RUNNING状态,执行onPreExecute(),再由执行器启动任务。
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED: // 同一个任务实例只能够执行一次
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture); // 开始进入后台线程执行任务
return this;
}
mWorker带着传进来的参数,mFuture实例化时已经将mWorker注入。参看构造函数
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 在后台线程进行自定义的操作 这里面可以调用publishProgress方法
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result); // 发送最终结果
}
};
mFuture = new FutureTask<Result>(mWorker) { // 依赖 mWorker
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
publishProgress方法通过主线程的Handler向外通知进度
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
后台任务执行完毕,postResult发送最终结果
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget(); // 会走到finish方法
return result;
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result); // 如果任务已经被取消了
} else {
onPostExecute(result); // 通知任务执行完毕
}
mStatus = Status.FINISHED;
}
sDefaultExecutor 和线程池源码中构建了一个线程池和一个自定义的执行器SerialExecutor。靠它们来执行后台任务。
参考源代码
public abstract class AsyncTask<Params, Progress, Result> {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 核心线程至少2个,最多4个
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
public static final Executor THREAD_POOL_EXECUTOR; // 实际执行者
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
// 默认执行器的类
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
}
backup at http://rustfisher.github.io/2017/06/22/Android_note/Android-AsyncTask/
微信关注我们
转载内容版权归作者及来源网站所有!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。
Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。
Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。