在UI线程中进行通信时链接一系列操作

时间:2018-02-08 13:52:00

标签: android ui-thread

我正在设计一个小应用程序,每秒用随机字母更改TextView

现在,我的代码看起来像这样并且效果很好:

@BindView(R.id.textview_letter) TextView letterTV;
private static final int DELAY_MILLIS = 1000;
private static final int LOOP_MAX = 10;
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private Handler h = new Handler();
private Random random = new Random();
private int position = 0;

private Runnable run = new Runnable() {
    @Override
    public void run() {
        if (position >= LOOP_MAX) {
            letterTV.setText("THE END !");
            h.removeCallbacks(run);
        } else {
            String randomLetter = String.valueOf(ALPHABET.charAt(random.nextInt(ALPHABET.length())));
            letterTV.setText(randomLetter);
            h.postDelayed(run, DELAY_MILLIS);
            position++;
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mylayout);
    ButterKnife.bind(this);
    h.post(run);
}

我现在想通过在每个字母之间将TextView的背景设置为黑色(或使其不可见)几毫秒来改进它,因此如果在两个字母中有两倍相同的字母,则通知用户行。

我唯一的想法就是在我的Runnable中添加另一个Runnable并使用拆分延迟处理它们(例如700和300毫秒),但这看起来非常复杂。

这样做的正确方法是什么?
(顺便说一句,Runnable / Handler真的是我最适合使用的模式吗?)

编辑:在非UI线程中我可以做这样的事情:

while (randomLetter.next()) {
    letterTV.setText(randomLetter);
    Thread.sleep(700);
    letterTV.setBackgroundColor(Color.BLACK);
    Thread.sleep(300);
}

1 个答案:

答案 0 :(得分:3)

使用RxAndroid,会降低复杂性:

public class Test extends AppCompatActivity {

    private Disposable randomLetterObservable;
    private TextView textView;
    private Random random = new Random();
    private final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);

        randomLetterObservable = Observable.interval(500L, TimeUnit.MILLISECONDS)
                .timeInterval()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Timed<Long>>() {
                    @Override
                    public void accept(Timed<Long> longTimed) throws Exception {
                        String randomLetter = String.valueOf(ALPHABET.charAt(random.nextInt(ALPHABET.length())));
                        textView.setText(randomLetter);
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (randomLetterObservable != null) {
            randomLetterObservable.dispose();
        }
    }
}

有依赖关系:

implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.8'

编辑:这是一个经过修改的解决方案,如果连续两次出现相同的字母,也会更改背景。

public class Test extends AppCompatActivity {

    private Disposable randomLetterObservable;
    private TextView textView;
    private Random random = new Random();
    private final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private String lastLetter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);

        randomLetterObservable = Observable.interval(700L, TimeUnit.MILLISECONDS)
                .timeInterval()
                .observeOn(AndroidSchedulers.mainThread())
                .switchMap(new Function<Timed<Long>, ObservableSource<String>>() {
                    @Override
                    public ObservableSource<String> apply(Timed<Long> longTimed) throws Exception {
                        String randomLetter = String.valueOf(ALPHABET.charAt(random.nextInt(ALPHABET.length())));
                        if (randomLetter.equals(lastLetter)) {
                            textView.setBackgroundColor(Color.BLACK);
                            return Observable.just(randomLetter)
                                    .observeOn(Schedulers.computation())
                                    .debounce(300L, TimeUnit.MILLISECONDS);
                        } else {
                            lastLetter = randomLetter;
                            return Observable.just(randomLetter);
                        }
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        textView.setText(s);
                        textView.setBackgroundColor(Color.TRANSPARENT);
                    }
                });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (randomLetterObservable != null) {
            randomLetterObservable.dispose();
        }
    }
}

事件在后台线程中发出,背景颜色和字母在主线程上设置。我认为这几乎就是你所要求的。 (您可能需要使用这些值来获得所需的效果)。

祝你好运。