我正在从事游戏项目。我想将游戏的每个视图关联到其各自的线程,然后根据该线程中运行的逻辑来更新视图。
为简单起见,我将发布一个示例:
这是Main Activity类,它将实现UI:
public class Main extends Activity{
private View root;
private boolean ready = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
setContentView(R.layout.s_main);
root = findViewById(R.id.root);
ViewTreeObserver vto = root.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
root.getViewTreeObserver().removeOnPreDrawListener(this);
ready = true;
return true;
}
});
}
public void start(View view) {
try {
if (ready && !Threads.run) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new AsyncTasks(this, R.id.txv1).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new AsyncTasks(this, R.id.txv2).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new AsyncTasks(this, R.id.txv1).execute();
new AsyncTasks(this, R.id.txv2).execute();
}
} else {
Threads.run = false;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这是AsyncTask扩展类,用于更新View:
public class AsyncTasks extends AsyncTask<Void, Void, String> {
private TextView view;
private boolean breakMove;
private String updateError;
public AsyncTasks(Activity activity, int viewId) {
breakMove = false;
updateError = null;
view = activity.findViewById(viewId);
}
@Override
protected String doInBackground(Void... voids) {
String message;
Threads.run = true;
try {
while (!breakMove) {
publishProgress();
Thread.sleep(100);
}
message = updateError != null ? updateError : "Thread Ends";
} catch (Exception ex) {
ex.printStackTrace();
message = ex.getMessage();
}
return message;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
try {
breakMove = !Threads.run;
if (view != null)
view.setText(String.valueOf(Math.random() * 100));
} catch (Exception ex) {
breakMove = true;
ex.printStackTrace();
updateError = ex.getMessage();
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Threads.run = false;
}
}
这很好。但是有局限性:
AsyncTask用于短时线程,而不用于Game或Long Running Thread项目。
在最新的android框架中,只能同时运行5个AsyncTask线程,其余线程将处于等待队列中。因此,如果我的项目需要同时更新5个以上的视图,它将无法正常工作。
我尝试过的事情:
其他所有Thread实现(如Runnable,Handler,Service等)都不允许更新视图。请记住,我的线程是在单独的外部文件或类中编码的。
runOnUiThread,因为它在UI线程上运行,因此它将使Main线程一直忙碌,并且在调用它的线程结束后,其输出也很明显。
我正在寻找一个简单的干净解决方案,就像我上面编写的那样,可以通过多个线程实现多视图更新。
预先感谢
答案 0 :(得分:0)
我找到了解决方案。简单干净:
public class Main extends Activity{
private View root;
private Runs runs;
private boolean ready = false;
private final Context context = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
setContentView(R.layout.s_main);
runs = new Runs(this);
root = findViewById(R.id.root);
//
ViewTreeObserver vto = root.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
root.getViewTreeObserver().removeOnPreDrawListener(this);
ready = true;
return true;
}
});
}
private void startRuns() {
try {
runs.run();
Threads.run = true;
} catch (Exception ex) {
Alerts.alert(context, ex.getMessage());
}
}
public void start(View view) {
try {
if (ready && !Threads.run) {
startRuns();
} else {
Threads.pause = !Threads.pause;
}
} catch (Exception ex) {
ex.printStackTrace();
Alerts.alert(context, ex.getMessage());
}
}
}
public class Runs implements Runnable {
private int count;
private Handler handler;
private TextView view1, view2;
public Runs(Activity activity) {
count = 0;
handler = new Handler();
view1 = activity.findViewById(R.id.txv1);
view2 = activity.findViewById(R.id.txv2);
}
@Override
public void run() {
if (!Threads.pause) {
update();
}
handler.postDelayed(this, Threads.sleep);
}
private void update() {
view1.setText(String.valueOf(count++));
view2.setText(String.valueOf(Math.random() * 100));
}
}