You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AsyncTask无法及时向主线程返回结果,求替代Thread.Sleep的方案

解决AsyncTask异步结果无法及时返回的问题

兄弟,你这个问题我太熟了!核心原因就是AsyncTask是异步执行的,主线程不会等待它完成后台任务就继续往下走,所以你在按钮点击事件里直接访问userPinRetrieved的时候,数据库请求可能还没结束,自然拿到的是null。用Thread.sleep()完全是饮鸩止渴——它会阻塞主线程,导致APP卡顿、无响应,甚至触发ANR(应用无响应)弹窗,绝对不能用!

下面给你两种靠谱的解决方案,先解决你当前用AsyncTask的问题,再给你推荐现代Android开发的替代方案:

一、正确使用AsyncTask的onPostExecute方法

AsyncTask设计的时候就考虑了这个问题:doInBackground在后台线程执行任务,任务完成后会自动调用运行在主线程的onPostExecute方法,你所有需要用到返回结果的逻辑(比如验证PIN、跳转页面、弹Toast)都应该放在这里,而不是主线程的点击事件里。

修改后的AsyncTask代码

public class AsyncTaskRunner extends AsyncTask<String, String, String> {
    // 用弱引用持有Activity,避免内存泄漏
    private WeakReference<UserLogin> activityReference;
    private String userPinRetrieved;

    // 构造方法传入当前Activity
    public AsyncTaskRunner(UserLogin activity) {
        this.activityReference = new WeakReference<>(activity);
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            // 你的数据库请求逻辑
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                JSONObject json = new JSONObject(line);
                Log.d("Line", line);
                // 注意:JSONObject的getString不会返回null,不存在的key会抛异常,所以用isNull判断
                if (json.isNull("userPin")) {
                    userPinRetrieved = "PIN NOT RECEIVED";
                    Log.d("userpin", userPinRetrieved);
                } else {
                    userPinRetrieved = json.getString("userPin");
                    Log.d("userpin", userPinRetrieved);
                }
            }
        } catch (Exception e) {
            Log.v("ErrorAPP", e.toString());
            userPinRetrieved = "ERROR";
        }
        // 将结果返回给onPostExecute
        return userPinRetrieved;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        // 先检查Activity是否还存在,避免内存泄漏和空指针
        UserLogin activity = activityReference.get();
        if (activity == null || activity.isFinishing()) {
            return;
        }

        // 所有需要用到结果的逻辑都放在这里!
        String userPin = activity.userPin;
        String employee = activity.employee;
        
        Toast.makeText(activity, result + " " + userPin, Toast.LENGTH_LONG).show();
        if (userPin.equals(result)) {
            Toast.makeText(activity, "Access Granted!", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(activity.getApplicationContext(), MainActivity.class);
            activity.startActivity(intent);
            Toast.makeText(activity, "Hello " + employee, Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(activity, "Access Denied! Incorrect Pin", Toast.LENGTH_SHORT).show();
        }
    }
}

修改后的按钮点击事件

signIn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 创建AsyncTask时传入当前Activity的引用
        AsyncTaskRunner postReq = new AsyncTaskRunner(UserLogin.this);
        postReq.execute("start");
        // 这里不要再放任何需要用到userPinRetrieved的逻辑!
    }
});

二、AsyncTask已被弃用,推荐现代替代方案

从Android API 30开始,AsyncTask已经被官方弃用了,推荐用更灵活、更安全的方式处理异步任务:

1. Java项目:ExecutorService + Handler

用线程池执行后台任务,再通过Handler回到主线程处理结果:

signIn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 创建单线程池执行后台任务
        ExecutorService executor = Executors.newSingleThreadExecutor();
        // 获取主线程的Handler
        Handler handler = new Handler(Looper.getMainLooper());

        executor.execute(() -> {
            String userPinRetrieved = null;
            try {
                // 后台执行数据库请求
                BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String line;
                while ((line = br.readLine()) != null) {
                    JSONObject json = new JSONObject(line);
                    Log.d("Line", line);
                    userPinRetrieved = json.isNull("userPin") ? "PIN NOT RECEIVED" : json.getString("userPin");
                }
            } catch (Exception e) {
                Log.v("ErrorAPP", e.toString());
                userPinRetrieved = "ERROR";
            }

            final String result = userPinRetrieved;
            // 回到主线程处理结果
            handler.post(() -> {
                String userPin = UserLogin.this.userPin;
                String employee = UserLogin.this.employee;
                
                Toast.makeText(UserLogin.this, result + " " + userPin, Toast.LENGTH_LONG).show();
                if (userPin.equals(result)) {
                    Toast.makeText(UserLogin.this, "Access Granted!", Toast.LENGTH_SHORT).show();
                    startActivity(new Intent(getApplicationContext(), MainActivity.class));
                    Toast.makeText(UserLogin.this, "Hello " + employee, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(UserLogin.this, "Access Denied! Incorrect Pin", Toast.LENGTH_SHORT).show();
                }
            });
        });
    }
});

2. Kotlin项目:Coroutines(协程)

协程是Kotlin官方推荐的异步处理方式,代码更简洁、安全:

signIn.setOnClickListener {
    // 用lifecycleScope绑定Activity生命周期,避免内存泄漏
    lifecycleScope.launch {
        // 在IO线程执行后台任务
        val result = withContext(Dispatchers.IO) {
            var userPinRetrieved: String? = null
            try {
                val br = BufferedReader(InputStreamReader(con.inputStream))
                var line: String?
                while (br.readLine().also { line = it } != null) {
                    val json = JSONObject(line!!)
                    Log.d("Line", line!!)
                    userPinRetrieved = if (json.isNull("userPin")) "PIN NOT RECEIVED" else json.getString("userPin")
                }
            } catch (e: Exception) {
                Log.v("ErrorAPP", e.toString())
                userPinRetrieved = "ERROR"
            }
            userPinRetrieved
        }

        // 主线程处理结果
        Toast.makeText(this@UserLogin, "$result $userPin", Toast.LENGTH_LONG).show()
        if (userPin == result) {
            Toast.makeText(this@UserLogin, "Access Granted!", Toast.LENGTH_SHORT).show()
            startActivity(Intent(applicationContext, MainActivity::class.java))
            Toast.makeText(this@UserLogin, "Hello $employee", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this@UserLogin, "Access Denied! Incorrect Pin", Toast.LENGTH_SHORT).show()
        }
    }
}

内容的提问来源于stack exchange,提问作者AndroidBeginner2018

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:07:43