java - 如何并行连续递增多个 RecyclerView 值
问题描述
语境
使用RecyclerView
每个都有标签和值的项目TextViews
,以及一个开始Button
。
目标
Button
开始并在按下开始时继续增加一个值- 必须可以通过其 Button 单独启动每个项目的值
- 一旦开始,多个值必须能够并行连续递增
问题
UI(值TextView
、点击Button
等)在 2 个或更多值开始递增后变慢。不确定如何处理线程(尝试过HandlerThread
/ runOnUiThread
,当前为每个MyValue
对象使用单独的线程),请参见下面MyValue.start()
的代码。
如何在RecyclerView
不减慢 UI 的情况下在更新的同时并行不断地增加单个值?
到目前为止已经尝试过什么
- 使用
HandlerThread
和runOnUiThread
Thread
对每个MyValue
对象使用个人- 考虑
AsyncTask
过,但在未来,“增加多个值”行为可能需要在后台独立运行Activity
(即,仅Activity
在前台更新 GUI),因此该行为可能会转移到BoundService
- 可以根据 中的值使用
LiveData
来RecyclerView
观察和更新项目MyValue
,但是,不确定 LiveData 可以如何使用MyValue
和ValuesAdapter
代码
主要活动
public class MainActivity extends AppCompatActivity {
ArrayList<MyValue> mValues;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
mValues = new ArrayList<>();
mValues.add(new MyValue("value 1"));
mValues.add(new MyValue("value 2"));
mValues.add(new MyValue("value 3"));
ValuesAdapter valuesAdapter = new ValuesAdapter(mValues);
recyclerView.setAdapter(valuesAdapter);
}
}
值适配器
public class ValuesAdapter extends RecyclerView.Adapter<ValuesAdapter.ValueViewHolder> {
private List<MyValue> mValues;
private Context mContext;
private ValueController mValueController;
public ValuesAdapter(List<MyValue> values) {
mValues = values;
mValueController = new ValueController(mValues);
}
@Override
public ValueViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mContext == null) {
mContext = parent.getContext();
}
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View valueView = layoutInflater.inflate(R.layout.value_item, parent, false);
return new ValueViewHolder(valueView);
}
@Override
public void onBindViewHolder(ValueViewHolder holder, int position) {
MyValue value = mValues.get(position);
String label = value.getLabel();
int currentValue = value.getValue();
holder.setupViewHolder(label, "" + currentValue);
value.setListener(holder);
}
@Override
public int getItemCount() {
return mValues.size();
}
class ValueViewHolder extends RecyclerView.ViewHolder
implements MyValue.ValueListener {
TextView mLabel;
TextView mValue;
Button mStart;
public ValueViewHolder(View itemView) {
super(itemView);
mLabel = itemView.findViewById(R.id.label);
mValue = itemView.findViewById(R.id.value);
mStart = itemView.findViewById(R.id.start);
}
public void setupViewHolder(String label, String currentValue) {
mLabel.setText(label);
mValue.setText(currentValue);
int adapterPosition = getAdapterPosition();
final MyValue value = mValues.get(adapterPosition);
mStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
value.start();
}
});
}
@Override
public void onTick(final int currentValue) {
mValueController.incActiveStopwatches();
((Activity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
mValue.setText("" + currentValue);
}
});
}
}
}
值控制器
public class ValueController {
private List<MyValue> mValues;
public ValueController(List<MyValue> values) {
mValues = values;
}
public void incrementActiveValues() {
for (int i = 0; i < mValues.size(); i++) {
MyValue value = mValues.get(i);
if (value.getShouldIncrement()) {
value.increment();
}
}
}
}
我的价值
public class MyValue {
private String mLabel;
private int mCurrentValue;
private boolean mShouldIncrement;
private Handler mHandler;
private ValueListener mListener;
public MyValue(String label) {
mLabel = label;
HandlerThread handlerThread = new HandlerThread("HandlerThread1");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
}
public String getLabel() {
return mLabel;
}
public int getValue() {
return mCurrentValue;
}
public void increment() {
mCurrentValue++;
}
public void start() {
mShouldIncrement = true;
new Thread(new Runnable() {
@Override
public void run() {
while (mShouldIncrement) {
increment();
if (mListener != null) {
mListener.onTick(mCurrentValue);
}
}
}
}).start();
// mHandler.post(new Runnable() {
// @Override
// public void run() {
// while (mShouldIncrement) {
// increment();
// if (mListener != null) {
// mListener.onTick(mCurrentValue);
// }
// }
// }
// });
}
public void setListener(ValueListener listener) {
mListener = listener;
}
public interface ValueListener {
void onTick(int currentValue);
}
public boolean getShouldIncrement() {
return mShouldIncrement;
}
}
解决方案
问题
似乎RecyclerView
TextView
通过MyValue.ValueListener.onTick()
.
解决方案
当前的解决方案是延迟onTick
到仅每 1 秒触发一次,即替换MyValue.start()
为:
private Runnable mRepeatIncrementRunnable = new Runnable() {
@Override
public void run() {
if (mShouldIncrement) {
increment();
if (mListener != null) {
mListener.onTick(mCurrentValue);
}
} else {
mHandler.removeCallbacks(this);
return;
}
mHandler.postDelayed(this, mTickIntervalMs);
}
};
public void start() {
mShouldIncrement = true;
mHandler.post(mRepeatIncrementRunnable);
}
推荐阅读
- flutter - 错误响应状态:12,InvalidElementState - 元素命令无法完成,因为元素处于无效状态
- c# - Xamarin 形成地理定位错误的结果
- java - 在 Android 应用程序上放弃表单时触发事件
- javascript - Is it okay to use an infinite loop to constantly check the Connection to a Server?
- javascript - 如何在反应虚拟化中检测滚动事件的结束?
- amazon-web-services - 加载命名空间时出错。未经授权:验证您有权访问 Kubernetes 集群
- javascript - splitslider.js - 打开一个特定的 div,而不是用箭头
- javascript - 如何在中间件中将 Koa bodyParser 上传限制设置为特定路由而不是全局?
- javascript - 在cropper js中上传图片会出错拒绝加载图片违反内容安全策略指令:“img-src * data:”
- kubernetes - 无法访问用完 istio 服务网格的 api