上下文
使用RecyclerView
个项目,每个项目都具有标签和值TextViews
,并带有一个起始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
代码
MainActivity
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);
}
}
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);
}
});
}
}
}
ValueController
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();
}
}
}
}
MyValue
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;
}
}
答案 0 :(得分:1)
问题
似乎通过RecyclerView
完成了很多工作(例如,在增加值和更新TextView
MyValue.ValueListener.onTick()
值时跳过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);
}