【问题标题】:Calling finish() from SurfaceView does not destroy Activity从 SurfaceView 调用 finish() 不会破坏 Activity
【发布时间】:2015-05-16 22:14:26
【问题描述】:

我想finish() 来自班级RenderView 的活动VideoPlayer。但是从RenderView 调用finish() 不会调用onDestroy()。 Activity 不会被销毁,也不会返回到之前的 Main Activity。

public class VideoPlayer extends Activity  {

    @Override
    protected void onPause(){
        super.onPause();
        renderView.pause();     
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        naClose2();
    }

}

mFinished = true 但它返回到调用finish() 的方法parseServerInfo() 并继续执行其余代码。

编辑

public class RenderView extends SurfaceView implements SurfaceHolder.Callback   {
    private Context mContext;

    private Runnable prDisplayVideoTask = new Runnable() {
        public void run() {
            if(zoomState.isPlaying()==false){
                if(zoomState.getFlag()==FlagType.PAUSE){
                    zoomState.setFlag(FlagType.NONE);
                    naPause();
                }
            } else {
                naStart();
            }
            prVideoDisplayHandler.postDelayed(this, prDelay);
        }
    };

    public RenderView(...) {
        super(_context);
        this.mContext = _context;
        init(address, windowWidth, windowHeight, videoWidth, videoHeight,
                server_ip, server_port);
        SurfaceHolder holder = getHolder();
        holder.setFormat(PixelFormat.RGBA_8888);
        holder.addCallback(this);
    }

    @SuppressLint("NewApi")
    public void init(...) {
        parseServerInfo(receivedData);
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }

    public void pause(){
        naPause();
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
    }

    public void resume(){
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }

    public void parseServerInfo(String data) {
        if (numCameras == 0) {
            Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

            // Finish is called here
            VideoPlayer videoplayer = (VideoPlayer) mContext;
            videoplayer.finish();
            return;
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mCreated  == true) {
            surfaceDestroyed(holder);
        }
        Surface surface = holder.getSurface();
        render(surface);
        mCreated = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCreated = false;
    }
}

希望有人能帮助指出我做错了什么。

【问题讨论】:

  • 我也是初学者。改用 getActivity(),因为你想完成活动。
  • @UmeshChhabra 如果我没记错的话,不可能从 SurfaceView 调用 getActivity()。因此,我使用 getContext() 来获取对 Activity 的引用。
  • getContext.getActivity();
  • 只需使用 ((VideoPlayer).getContext()).finish();您不需要保留对上下文的显式引用,您的视图已经引用了它。
  • @zgc7009 这就是我实现它的方式,我根据建议的解决方案使用了mContext。但是,两者都不能解决问题。

标签: java android android-activity surfaceview


【解决方案1】:

您必须在SurfaceView 中引用您想要完成的活动。您从SurfaceView 类的构造函数中获取上下文。用这个finish()你的活动,就像这样

//class member
private Context mContext;

public RenderView(...) {
    super(_context);

    //make the context accessible from the whole class
    this.mContext = _context;

    ...
}

最后,您在该上下文中调用 finish() 以完成您的 VideoPlayer 活动。

【讨论】:

  • 您是否将活动上下文传递给 RenderView 构造函数? @miazima
【解决方案2】:

这就是为什么它会继续并冻结(如您的问题的 cmets 中所述)。这应该。这就是java语言的工作原理。这里,

@SuppressLint("NewApi")
public void init(...) {
    parseServerInfo(receivedData);
    ...
}

你打电话给parseServerInfo(receivedData); 这样做

public void parseServerInfo(String data) {
    if (numCameras == 0) {
        Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

        // Finish is called here
        VideoPlayer videoplayer = (VideoPlayer)getContext();
        videoplayer.finish();
        return;
    }
}

所以你看到了 Toast,完成了,并说好。但你不会回头看你来自哪里。使用 cmets,你的 init 方法应该说的是

@SuppressLint("NewApi")
public void init(...) {
    // make a call to check that the number of cameras is not 0
    parseServerInfo(receivedData);    
    // AND CONTINUE NO MATTER WHAT...
    prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
    prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
}

你需要的是

public boolean parseServerInfo(String data) {
    if (numCameras == 0) {
        Toast.makeText(mContext, "No stream detected!", Toast.LENGTH_LONG).show();

        // Finish is called here... AND FALSE IS RETURNED
        VideoPlayer videoplayer = (VideoPlayer) mContext;
        videoplayer.finish();
        return false;
    }
    return true;
}

然后

@SuppressLint("NewApi")
public void init(...) {
    // make a call to check that the number of cameras is not 0
    // AND CONTINUE IF GOOD (TRUE)
    if(parseServerInfo(receivedData)){
        prVideoDisplayHandler.removeCallbacks(prDisplayVideoTask);
        prVideoDisplayHandler.postDelayed(prDisplayVideoTask, prDelay);
    }
}

这将解析您的数据,完成活动(如果应该),然后使用 SurfaceView 的 init 方法停止进度。抱歉有这么多冗余代码,但它最容易解释:P

【讨论】:

  • 按照您的建议更改代码结构!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 2013-01-04
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多