java - 如何从绘图线程(SurfaceView)调用另一个 Activity

标签 java android multithreading handler surfaceview

目标是这样的:
我启动应用程序,MainActivity启动绘图线程。
该线程进行绘制,直到其中发生一些事件为止(在我的情况下,值i> 155)
然后,该线程停止绘制(但不应删除它,并且值也不应丢失)并启动另一个 Activity (通常的xml-文件 Activity )
当我想要的时候,我应该能够进入我的绘图线程,并从我弯腰的地方继续与之通信

为了解决该问题,我决定在内部使用SurfaceView线程和Canvas(最好将其设为一个类,而不是在MainActivity中编写它,因为我将在其中插入很多代码)。我设法启动了一个线程并在屏幕上绘制了一些东西,但是我无法更改 Activity 。最好的尝试是在MainActivity中创建一个处理程序,并从我的线程那里发送一条消息。
该线程可以正常工作,但是它只是冻结并且在需要更改Activity时什么也没有发生。在日志选项卡中,我可以看到该线程发送了一条消息,但是MainActivity无法看到和处理它。

我该怎么办?解决问题的正确方法是什么?请帮助新手)。

MainActivity代码:

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类代码:
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();
            }


        }
    }
}

最佳答案

答案很简单:我必须将所有内容替换到一个文件中(放入MainAcitivity类,如https://startandroid.ru/ru/uroki/vse-uroki-spiskom/311-urok-141-risovanie-dostup-k-canvas.html),并创建一个可运行的 Activity ,将其称为 Activity 。然后,每次打开MainActivity时,图形线程都会启动,并且当需要更改Activity时,它将使用 runOnUIThread(runnable)调用可运行的; 。它暂停MainActivity并开始一个新的 Activity ( !!任何暂停的MainActivity都会破坏我们的图形线程,任何重新开始都会重新启动它,据我所知)。关闭新 Activity 后,您将返回MainActivity,我们的线程将再次启动。
如果您不想丢失图形线程的值,则可以在 Activity 类内而不是线程类内声明这些值(因为在关闭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);
                            }
                        }
                    }
                }
            }
        }

    }

}

关于java - 如何从绘图线程(SurfaceView)调用另一个 Activity ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62290338/

相关文章:

java - Android-如何在一个布局中显示拆分两个街景

java - 使用 future 和 completableFuture 中断读取方法

java - list 合并失败并出现多个错误,请参阅日志错误

java - 为 JSF 应用程序指定外部错误页面

安卓布局: one widget scrollable and two fixed at bottom

c - 如何让一个线程等待其他线程完成

java - 如何将变量从 Main Activity 传递到 AsyncTask 及其方法?

android - 为什么 ViewHolder 上的 OnClickListener 不起作用?

C# 线程参数在线程执行期间发生变化 - 为什么?

java - 简单Java服务中的并发问题