综合技术

PostInvalidate () does not work with non-ui thread

微信扫一扫,分享到朋友圈

PostInvalidate () does not work with non-ui thread
0

I am using a custom view to draw a game content and i use a button from xml layout to enable or disable the drawing of a specific content(rectangle) using separate thread.I managed to have the thread running but postInvalidate() method that i use is being ignored.I tried using setWillNotDraw(false) too.It isn’t working.I’ve condensed my code,to be specific on which part of the code i have this problem.

activity_main.xml



    

        

    

        

     

And this is my MainActivity.java

package com.example.temp;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

    Button b;
    Boolean lock=false;
    Cview v;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        v=new Cview(this,null);
        setContentView(R.layout.activity_main);
        initialize();
    }

    private void initialize() {
        // TODO Auto-generated method stub
        b=(Button) findViewById(R.id.bMineDetector);
        lock=false;
        b.setOnClickListener(this);
    }

    public void updateViewStart(){
        v.onStart();
    }

    public void updateViewStop(){
        v.onPause();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        if(v.isRunning==true)
        v.onPause();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.bMineDetector:
            if(lock==false){
                lock=true;
                updateViewStart();
                b.setText("UnLock");
            }else{
                lock=false;
                updateViewStop();
                b.setText("lock");
            }

            break;
        }
    }

}

In the above class i set a onClickListener that helps to start or stop a separate thread based on the state of the button.Here is my custom view where i handle touch events and also create this thread.

Cview.java

package com.example.temp;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class Cview extends View implements OnTouchListener,Runnable{

    Boolean isRunning=false,isLockMode=false;
    Context gameContext;
    Thread myThread=null;

    public Cview(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        gameContext=context;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        Log.d("INVALIDATE", "Invalidating");
        isLockMode=((MainActivity)gameContext).lock;
        if(isLockMode==true){
            canvas.drawRect(100, 100, 300, 300, null);
            //invalidate();
        }

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(isRunning){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            isLockMode=((MainActivity)gameContext).lock;
            this.postInvalidate();
            Log.d("THREAD", "isRunning="+isRunning+";;isLockMode="+isLockMode);
            }
    }

    void onStart(){
        isRunning=true;
        myThread=new Thread(this);
        myThread.start();
        //Log.d("INVALIDATE", "onStart");
        //postInvalidate();
    }

    void onPause(){
        isRunning=false;
        while(true){
            try {
                myThread.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        }
        myThread=null;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        return true;
    }

}

Please anyone help me with this.I need the canvas to be redrawn once the run method is being executed.Ive been thinking about this for months and I’m new to programming too.So please guide me and suggest me if there is any other better method to do what i need.Thank you.

As explained in What is the difference between Android’s invalidate() and postInvalidate() methods?, there might be some problems when postInvalidate is used from other threads.

I haven’t tested this and it’s not really nice, but it could help you (instead of this.postInvalidate();
)

((MainActivity) gameContext).runOnUiThread(new Runnable() {
       @Override
       public void run() {

           Cview.this.invalidate();

       }
 });

阅读原文...


Hello, buddy!

B站终于拿下洛天依,虚拟偶像为何引得大佬们竞相布局?

上一篇

活久见!马斯克内部邮件称特斯拉已经十分接近盈利

下一篇

您也可能喜欢

评论已经被关闭。

插入图片
PostInvalidate () does not work with non-ui thread

长按储存图像,分享给朋友