在 UI 线程中通信时链接一系列操作
Chaining a sequence of actions when communicating in a 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);
}
使用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();
}
}
}
事件在后台线程中发出,背景颜色和字母在主线程中设置。我认为这几乎就是您所要求的。 (您可能需要调整这些值以获得所需的效果)。
祝你好运。
我正在设计一个小型应用程序,它每秒用一个随机字母更改 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);
}
使用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();
}
}
}
事件在后台线程中发出,背景颜色和字母在主线程中设置。我认为这几乎就是您所要求的。 (您可能需要调整这些值以获得所需的效果)。
祝你好运。