当前位置: 首页 > 知识库问答 >
问题:

自定义异步任务的实现不起作用

方寒
2023-03-14

我正在尝试创建自己的android Asynctask实现。为此,我创建了一个抽象类,它扩展了Thread类。我为onPreExecute、onPostExecute、onProgressUpdate和doInBackground声明了方法。

我通过从主线程的循环器创建一个处理程序来运行doInBackground方法。但我无法修改onProgressUpdate()方法中的UI元素,但我可以修改onPostExecute()方法中的UI元素。

这是我试过的。

package com.example.myapplication;

import android.os.Handler;
import android.os.Looper;

public abstract class MyAsyncTask extends Thread {
        String[] urls;
        Handler handler;

        abstract protected void onPreExecute();

        abstract protected void onPostExecute(String result);

        abstract protected void onProgressUpdate(String result);

        protected void publishProgress(String progress) {
            onProgressUpdate(progress);
        }

        abstract protected void doInBackground(String... urls);


        protected void execute(String... urls) {
            onPreExecute();
            this.urls = urls;
            start();
        }

        public void run() {
            try {
                handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        doInBackground(urls);
                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

这是我的主活动。它有进度条和进度文本来显示进度。

package com.example.myapplication;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    ProgressBar bar;
    TextView progressText;
    LinearLayout container;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bar = findViewById(R.id.progress);
        progressText = findViewById(R.id.progressText);
        container = findViewById(R.id.container);
    }

    public void startProcess(View view) {
        String[] assignments = {"assgn1", "assgn2", "assgn3", "assgn4", "assgn5"};

        new ProgressAsync().execute(assignments);
    }

    public void showProgress() {
        container.setVisibility(View.VISIBLE);
    }

    public void hideProgress() {
        container.setVisibility(View.GONE);
    }

    public class ProgressAsync extends MyAsyncTask {

        @Override
        protected void onPreExecute() {
            showProgress();
        }

        @Override
        protected void onPostExecute(String result) {
            progressText.setText("All processed");
            hideProgress();
        }

        @Override
        protected void onProgressUpdate(String result) {
            progressText.setText(result + "  processed");
        }

        @Override
        protected void doInBackground(String... urls) {
            for (int i = 0; i < urls.length; i++) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                publishProgress(this.urls[i]);
            }
            onPostExecute("SUCCESS");
        }
    }


}

它应该设置进度每2秒后像assgn1,assgn2等文本。但是它不会在onProgressUpdate()期间为进步文本设置任何文本,而是在onPostExecute()方法中设置“所有已处理”。

如果我在这里错过了什么,有人能帮我吗?

共有1个答案

淳于枫
2023-03-14

在实现自己的异步任务之前,需要了解一些规则

AsyncTask允许正确且轻松地使用UI线程。此类允许您在UI线程上执行后台操作和发布结果,而无需操纵线程和/或处理程序

  1. AsyncWG将产生至少一个后台线程来完成其工作。
  2. doInbackground()将在这个后台线程上运行,因为如果它在UI线程上运行,您的应用程序将冻结甚至崩溃。
  3. onPreExecute()onPostExecute()onProgressUpdate()将在UI线程上运行。

在您的代码中,由于doInBackground()中的代码在UI线程上运行,因此您的应用程序会被冻结,直到到达doInBackground()方法中的最后一行。

下面是我的解决方案:

MyAsyncTask.java

public abstract class MyAsyncTask extends Thread {
    private String[] mUrls;
    private Handler mMainHandler;

    public MyAsyncTask() {
        // Using this handler to update UI
        mMainHandler = new Handler(Looper.getMainLooper());
    }

    abstract protected void onPreExecute();

    abstract protected void onPostExecute(String result);

    abstract protected void onProgressUpdate(String result);

    protected void publishProgress(final String progress) {
        // This will run in UI thread.
        mMainHandler.post(new Runnable() {
            @Override
            public void run() {
                onProgressUpdate(progress);
            }
        });
    }

    abstract protected String doInBackground(String... urls);

    protected void execute(String... urls) {
        mUrls = urls;
        start();
    }

    public void run() {
        // This will run in UI thread.
        mMainHandler.post(new Runnable() {
            @Override
            public void run() {
                onPreExecute();
            }
        });

        String result = null;
        try {
            // This will run in the background thread.
            result = doInBackground(mUrls);
        } finally {
            // This will run in UI thread.
            final String finalResult = result;
            mMainHandler.post(new Runnable() {
                @Override
                public void run() {
                    onPostExecute(finalResult);
                }
            });
        }
    }
}

ProgressAsync。JAVA

public class ProgressAsync extends MyAsyncTask {

    @Override
    protected void onPreExecute() {
        showProgress();
    }

    @Override
    protected void onPostExecute(String result) {
        progressText.setText(result);
        hideProgress();
    }

    @Override
    protected void onProgressUpdate(String result) {
        progressText.setText(result + "  processed");
    }

    @Override
    protected String doInBackground(String... urls) {
        for (String url : urls) {
            publishProgress(url);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "SUCCESS";
    }
}

注意:我只给出了简单而快速的解决方案,在实践中,您需要编写更多的代码来处理某些场景,例如处理异常、取消后台任务等。

 类似资料:
  • 我试图在这个类中实现异步任务,但问题是我在我的程序中调用了函数,该函数返回一个值,我不知道该把它放在哪里。在异步任务中,我应该在哪里定义?我得到以下例外 以下是我的主要课程: 这是我的解析类:公共类解析{ List headlines列出链接;列表描述;列出lstDate列出新日期;//字符串a,b,c,d;public InputStream getInputStream(URL URL){ t

  • 这类似于在无法使用两个带有Spring Boot/Spring数据Neo4j的Neo4j实例中讨论的内容,但我没有两个数据库。我从git repo下载了spring data neo4j示例java应用程序,希望执行动态查询,而不是通过存储库接口执行静态查询。 我面临一个空事务管理器的问题。 这是我的界面: 以下是我的自定义回购建议: 以下是我的配置: 因为我只有一个TransactionMana

  • 问: 如何异步处理繁重的业务,避免主业务被长时间阻塞。例如我要给1000用户发送邮件,这个过程很慢,可能要阻塞数秒,这个过程中因为主流程被阻塞,会影响后续的请求,如何将这样的繁重任务交给其它进程异步处理。 答: 可以在本机或者其它服务器甚至服务器集群预先建立一些任务进程处理繁重的业务,任务进程数可以开多一些,例如cpu的10倍,然后调用方利用AsyncTcpConnection将数据异步发送给这些

  • 我正在尝试为我的Vue自动化构建过程(Azure Devops)。使用“npm”任务的js应用程序。 为了安装节点包,我使用了内置的“安装”命令的npm任务。 对于构建过程,我已经部署了另一个npm任务,但是使用了自定义命令(构建)。此自定义生成命令成功运行,但出现以下警告 "npm WARN build'npm build'不带参数调用。你是说'npm run-script build'吗?"

  • 问题内容: 我正在尝试呈现jtable的特定行(它应该具有不同的背景色,并且应该具有粗体字符)。 我发现了几个有关如何实现自定义的问题,以及有关如何使用表以及本教程(表行渲染)的问题。 我正在使用来显示。我尝试实现两种解决方案,但都没有实现。调试时,可以看到正在创建新的jtable,但是没有调用方法中的断点。 我的代码如下: 如您所见,模型是我对的实现。 当然,我缺少了一些东西。我试图打电话看看是

  • 我将symfony 3迁移到symfony 4.3,并且我的自定义包移动到:src/Bundles/FooBundle。 structure FooBundle:-依赖注入-配置。php-FooExtension。php-Event-Model-Resources-config-services。yml-Service-Twig-Exception-FooBundle。php 和文件bundle/