如何从绘图线程 (SurfaceView) 调用另一个 activity
How to call another activity from drawing thread (SurfaceView)
目标是这样的:
我启动应用程序,MainActivity 启动绘图线程。
这个线程一直绘制直到它里面的一些事件发生(在我的例子中值 i>155)
然后这个线程停止绘制(但它不应该被删除,并且值不应该丢失)并开始另一个 activity(一个通常的 xml - 文件 activity)
当我想要的时候,我应该能够到达我的绘图线程并从我弯腰的地方恢复与它的通信
为了解决这个问题,我决定在里面使用一个SurfaceView线程和Canvas(最好把它写成class,不要写在MainActivity里面,因为我要在那里插入很多代码)。我设法启动了一个线程并在我的屏幕上画了一些东西,但我无法更改 activity。最好的尝试是在 MainActivity 中创建一个处理程序,并从我的线程向那里发送一条消息。
该线程工作正常,但它只是冻结并且在更改 Activity 时没有任何反应。在日志选项卡中我可以看到线程发送了一条消息,但是 MainActivity 看不到并处理它。
我该怎么办?解决问题的正确方法是什么?请帮助初学者)。
主要Activity代码:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
public Handler h =new Handler() {
public void handleMessage(android.os.Message msg) {
Log.i("","recieved");
if(msg.what==1){
Intent intent = new Intent(MainActivity.this,ScrollingActivity.class);
MainActivity.this.startActivity(intent);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(getHolder());
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
}
DrawThread class代码:
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
class DrawThread extends Thread {
Canvas canvas;
int i=0;
private boolean running = false;
private SurfaceHolder surfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Looper.prepare();
while (running) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
draw();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
public void draw(){
canvas.drawColor(Color.rgb(i,i,i));
i++;
if(i>155){
i=0;
running=false;
sender snd = new sender();
snd.send(1);
}
}
private class sender extends MainActivity{
public void send(int i){
Log.i("","sending");
try {
h.sendEmptyMessage(i);
Log.i("","sent");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
答案是 easy:I 必须将所有内容替换到一个文件中(替换到 MainAcitivity class,如此处 https://startandroid.ru/ru/uroki/vse-uroki-spiskom/311-urok-141-risovanie-dostup-k-canvas.html)并创建一个可运行的,调用 activity.然后每次打开 MainActivity 图形线程都会启动,当需要更改 Activity 时,它会使用 runOnUIThread(runnable) 调用该可运行对象; 。它暂停 MainActivity 并启动一个新的 activity(!!任何暂停 MainActivity 都会破坏我们的图形线程,任何恢复都会再次启动它,据我所知)。在关闭新的 activity 时,您将返回到 MainActivity 并且我们的线程再次启动。
如果您不想丢失图形线程的值,您可以在 activity class 中声明这些值,而不是在线程 class 中声明这些值(因为线程将在关闭Activitie 的屏幕。(我没有看到任何其他出路)
P. S. 如有错误,请指正。但是代码应该可以正常工作。
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
int i=0;
//boolean firstRun=true;
Runnable call = new Runnable() {
public void run() {
Log.i("","recieved");
Intent intent=new Intent(MainActivity.this,ScrollingActivity.class);
startActivity(intent);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i("","created");
drawThread = new DrawThread(getHolder());
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("","destroyed");
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class DrawThread extends Thread {
private boolean drawing=true;
private boolean running = false;
private SurfaceHolder surfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas canvas;
while (running) {
Log.i("","running");
if (drawing) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
if (canvas == null)
continue;
canvas.drawColor(Color.rgb(i, i, i));
i++;
if (i == 100) {
drawing = false;
runOnUiThread(call);
}
if(i>255){
i=0;
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
}
}
目标是这样的: 我启动应用程序,MainActivity 启动绘图线程。 这个线程一直绘制直到它里面的一些事件发生(在我的例子中值 i>155) 然后这个线程停止绘制(但它不应该被删除,并且值不应该丢失)并开始另一个 activity(一个通常的 xml - 文件 activity) 当我想要的时候,我应该能够到达我的绘图线程并从我弯腰的地方恢复与它的通信
为了解决这个问题,我决定在里面使用一个SurfaceView线程和Canvas(最好把它写成class,不要写在MainActivity里面,因为我要在那里插入很多代码)。我设法启动了一个线程并在我的屏幕上画了一些东西,但我无法更改 activity。最好的尝试是在 MainActivity 中创建一个处理程序,并从我的线程向那里发送一条消息。 该线程工作正常,但它只是冻结并且在更改 Activity 时没有任何反应。在日志选项卡中我可以看到线程发送了一条消息,但是 MainActivity 看不到并处理它。
我该怎么办?解决问题的正确方法是什么?请帮助初学者)。
主要Activity代码:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
public Handler h =new Handler() {
public void handleMessage(android.os.Message msg) {
Log.i("","recieved");
if(msg.what==1){
Intent intent = new Intent(MainActivity.this,ScrollingActivity.class);
MainActivity.this.startActivity(intent);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(getHolder());
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
}
DrawThread class代码:
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
class DrawThread extends Thread {
Canvas canvas;
int i=0;
private boolean running = false;
private SurfaceHolder surfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Looper.prepare();
while (running) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
draw();
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
public void draw(){
canvas.drawColor(Color.rgb(i,i,i));
i++;
if(i>155){
i=0;
running=false;
sender snd = new sender();
snd.send(1);
}
}
private class sender extends MainActivity{
public void send(int i){
Log.i("","sending");
try {
h.sendEmptyMessage(i);
Log.i("","sent");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
答案是 easy:I 必须将所有内容替换到一个文件中(替换到 MainAcitivity class,如此处 https://startandroid.ru/ru/uroki/vse-uroki-spiskom/311-urok-141-risovanie-dostup-k-canvas.html)并创建一个可运行的,调用 activity.然后每次打开 MainActivity 图形线程都会启动,当需要更改 Activity 时,它会使用 runOnUIThread(runnable) 调用该可运行对象; 。它暂停 MainActivity 并启动一个新的 activity(!!任何暂停 MainActivity 都会破坏我们的图形线程,任何恢复都会再次启动它,据我所知)。在关闭新的 activity 时,您将返回到 MainActivity 并且我们的线程再次启动。 如果您不想丢失图形线程的值,您可以在 activity class 中声明这些值,而不是在线程 class 中声明这些值(因为线程将在关闭Activitie 的屏幕。(我没有看到任何其他出路)
P. S. 如有错误,请指正。但是代码应该可以正常工作。
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
int i=0;
//boolean firstRun=true;
Runnable call = new Runnable() {
public void run() {
Log.i("","recieved");
Intent intent=new Intent(MainActivity.this,ScrollingActivity.class);
startActivity(intent);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i("","created");
drawThread = new DrawThread(getHolder());
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("","destroyed");
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class DrawThread extends Thread {
private boolean drawing=true;
private boolean running = false;
private SurfaceHolder surfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas canvas;
while (running) {
Log.i("","running");
if (drawing) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
if (canvas == null)
continue;
canvas.drawColor(Color.rgb(i, i, i));
i++;
if (i == 100) {
drawing = false;
runOnUiThread(call);
}
if(i>255){
i=0;
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
}
}
}