上下文
使用 RecyclerView
项目,每个项目都有标签和值 TextViews
,以及一个开始 Button
。
目标
- 在按下开始
按钮
时开始并继续递增一个值 - 必须能够通过其按钮单独启动每个项目的值
- 一旦启动,多个值必须能够并行连续递增
问题
UI(值 TextView
、单击 Button
等)在 2 个或更多值开始递增后变慢。不确定如何处理线程(尝试过 HandlerThread
/runOnUiThread
,目前为每个 MyValue
对象使用单独的线程),请参阅 MyValue.start( )
在下面的代码中。
如何在不减慢 UI 的情况下,在更新 RecyclerView
的同时连续并行增加各个值?
到目前为止尝试了什么
- 使用
HandlerThread
和runOnUiThread
- 为每个
MyValue
对象使用单独的Thread
- 考虑过
AsyncTask
,但将来“增加多个值”行为可能需要独立于Activity
在后台运行(即,仅更新 GUI当Activity
处于前台时),因此行为可能会转移到BoundService
- 可以使用
LiveData
让RecyclerView
项目根据MyValue
中的值进行观察和更新,但是,不确定 LiveData 如何可以与MyValue
和ValuesAdapter
一起使用
代码
主要 Activity
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);
}
});
}
}
}
值 Controller
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();
}
}
}
}
我的值(value)
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;
}
}
最佳答案
问题
似乎是通过 MyValue.ValueListener.onTick 完成了高频率的工作(即,在增加值和更新
。RecyclerView
TextView
值时跳过大约 2000 帧) ()
解决方案
当前的解决方案是延迟 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);
}
关于java - 如何并行连续递增多个 RecyclerView 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52138669/