Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从加载器向TextView添加文本_Java_Android_Classloader_Greenrobot Eventbus 3.0 - Fatal编程技术网

Java 如何从加载器向TextView添加文本

Java 如何从加载器向TextView添加文本,java,android,classloader,greenrobot-eventbus-3.0,Java,Android,Classloader,Greenrobot Eventbus 3.0,现在我正在研究线程,我的任务是制作一个计数器,它将在Loader的帮助下将数字从0添加到9。当然,我知道它不是使用Loader执行此类任务的最佳变体,但我想了解它是如何工作的 因此,我有以下代码: package asus.example.com.exercise4; import android.annotation.SuppressLint; import android.content.Context; import android.os.SystemClock; import andr

现在我正在研究线程,我的任务是制作一个计数器,它将在Loader的帮助下将数字从0添加到9。当然,我知道它不是使用Loader执行此类任务的最佳变体,但我想了解它是如何工作的

因此,我有以下代码:

package asus.example.com.exercise4;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class LoaderActivity extends AppCompatActivity {

    private TextView counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_threads);
        Button startButton = findViewById(R.id.start_button);
        Button cancelButton = findViewById(R.id.cancel_button);
        startButton.setOnClickListener(listener);
        cancelButton.setOnClickListener(listener);
        counter = findViewById(R.id.counter);
    }

    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.start_button:
                    getSupportLoaderManager().initLoader(0, null, new LoaderClass());
                    break;
                case R.id.cancel_button:
                    break;
            }
        }
    };



    @SuppressLint("StaticFieldLeak")
    class AsyncTaskLoaderClass extends AsyncTaskLoader<Void>{

        AsyncTaskLoaderClass(@NonNull Context context) {
            super(context);
        }

        @Nullable
        @Override
        public Void loadInBackground() {
            for (int i = 0; i<10;i++){
                counter.setText(i);
                SystemClock.sleep(500);
            }
            return null;
        }
    }

    private class LoaderClass implements LoaderManager.LoaderCallbacks<Void>{

        @NonNull
        @Override
        public Loader<Void> onCreateLoader(int i, @Nullable Bundle bundle) {
            return new LoaderActivity.AsyncTaskLoaderClass(LoaderActivity.this);
        }

        @SuppressLint("SetTextI18n")
        @Override
        public void onLoadFinished(@NonNull Loader<Void> loader, Void aVoid) {
            counter.setText("Done!");
        }

        @Override
        public void onLoaderReset(@NonNull Loader<Void> loader) {

        }
    }



}
是的,我理解,这意味着AsyncTaskLoaderClass应该位于另一个文件或静态文件中,但在这种情况下,我将没有机会向textview添加文本。那么,我该如何解决这个问题呢

UPD

我在单击“开始”按钮时以以下方式更改了代码:

case R.id.start_button:
                Loader loader = getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
                loader.forceLoad();
                Log.i(TAG, "Button start clicked");
                break;
现在每次在循环中,我都有以下错误:

E/e.com.exercise: Invalid ID 0x00000009.
E/EventBus: Could not dispatch event: class asus.example.com.exercise4.LoaderActivity$MyAsyncTaskLoader$ProgressEvent to subscribing class class asus.example.com.exercise4.LoaderActivity
    android.content.res.Resources$NotFoundException: String resource ID #0x9
UPD 2

最后通过以下方式修复了该问题:

现在


也许我不明白它为什么会工作,但它可以工作

使textview成为公共静态,就像这个公共静态textview计数器一样

您正在活动类中使用内部AsyncTaskLoaderClass。内部类保存外部类的引用。这意味着您的AsyncTaskLoader类在某些情况下可能持有活动引用。使您的内部类保持静态


您有两种解决方案。将AsyncTaskLoaderClass设置为单独的类文件或将AsyncTaskLoaderClass设置为静态类。

使活动实现LoaderCallbacks。此外,加载器在其onLoadFinished回调中检索一个特定值,因此它应该返回检索到的已加载项

要更改加载器加载的值,您需要使用新的参数包重新启动加载器,并传入参数,以便它知道它在做什么

然后,您再次尝试在AsyncTask中创建类似publishProgress的内容;如果您有冒险精神,加载程序无法立即执行,并且需要发送事件处理程序线程的一些变体,但很可能是一个,请参阅实现“org.greenrobot:eventbus:3.1.1”

TL;医生:用这个

public class LoaderActivity extends AppCompatActivity  implements LoaderManager.LoaderCallbacks<Void> {
    private TextView counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_threads);

        Button startButton = findViewById(R.id.start_button);
        Button cancelButton = findViewById(R.id.cancel_button);
        counter = findViewById(R.id.counter);
        startButton.setOnClickListener((view) -> {
            getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
        });
        cancelButton.setOnClickListener((view) -> {
            // do nothing, apparently
        });

        EventBus.getDefault().register(this);
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLoaderProgressEvent(MyAsyncTaskLoader.ProgressEvent event) {
        counter.setText("" + event.getNumber());
    }

    @NonNull
    @Override
    public Loader<Void> onCreateLoader(int i, @Nullable Bundle bundle) {
        return new MyAsyncTaskLoader(LoaderActivity.this);
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onLoadFinished(@NonNull Loader<Void> loader, Void aVoid) {
        counter.setText("Done!");
    }

    @Override
    public void onLoaderReset(@NonNull Loader<Void> loader) {

    }

    public static class MyAsyncTaskLoader extends AsyncTaskLoader<Void> {
        public static class ProgressEvent {
            private final int number;

            public ProgressEvent(int number) {
                this.number = number;
            }

            public int getNumber() { return number; }
        }

        public MyAsyncTaskLoader(@NonNull Context context) {
            super(context);
        }

        @Nullable
        @Override
        public Void loadInBackground() {
            for (int i = 0; i<10;i++){
                EventBus.getDefault().post(new ProgressEvent(i));
                SystemClock.sleep(500);
            }
            return null;
        }
    }
}

你能给我看一下在你的xml文件中添加文本视图的代码吗?你的文本视图id在Java文件中在哪里?@Niceumang,更新了问题否,不要这样做。非常感谢,我尝试了你的代码,但仍然不起作用。我想了一段时间,也许我错了,但问题可能是因为公共void onLoaderProgressEventMyAsyncTaskLoader.ProgressEvent事件未在任何地方使用,或者我不知道它应该如何工作如果您使用EventBus.getDefault.registerthis,那么EventBus将知道如何查找活动,因为它有一个用@Subscribe注释的方法,并且有一个ProgressEvent类型的参数。因此,可能我遗漏了一些东西,这是我的类的代码:,但当我在调试器中看到方法public Void loadInBackground根本没有被调用时,这很奇怪!但是,您可以尝试调用loader.forceLoad?更新问题
counter.setText(i);
counter.setText(""+i);
public class LoaderActivity extends AppCompatActivity  implements LoaderManager.LoaderCallbacks<Void> {
    private TextView counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_threads);

        Button startButton = findViewById(R.id.start_button);
        Button cancelButton = findViewById(R.id.cancel_button);
        counter = findViewById(R.id.counter);
        startButton.setOnClickListener((view) -> {
            getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
        });
        cancelButton.setOnClickListener((view) -> {
            // do nothing, apparently
        });

        EventBus.getDefault().register(this);
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        super.onDestroy();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onLoaderProgressEvent(MyAsyncTaskLoader.ProgressEvent event) {
        counter.setText("" + event.getNumber());
    }

    @NonNull
    @Override
    public Loader<Void> onCreateLoader(int i, @Nullable Bundle bundle) {
        return new MyAsyncTaskLoader(LoaderActivity.this);
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onLoadFinished(@NonNull Loader<Void> loader, Void aVoid) {
        counter.setText("Done!");
    }

    @Override
    public void onLoaderReset(@NonNull Loader<Void> loader) {

    }

    public static class MyAsyncTaskLoader extends AsyncTaskLoader<Void> {
        public static class ProgressEvent {
            private final int number;

            public ProgressEvent(int number) {
                this.number = number;
            }

            public int getNumber() { return number; }
        }

        public MyAsyncTaskLoader(@NonNull Context context) {
            super(context);
        }

        @Nullable
        @Override
        public Void loadInBackground() {
            for (int i = 0; i<10;i++){
                EventBus.getDefault().post(new ProgressEvent(i));
                SystemClock.sleep(500);
            }
            return null;
        }
    }
}