线程同步问题和动画问题,高手进来帮忙一下

xzx983 2018-04-17 12:28:04
这是我的思路

出现的问题:线程不会同步,问题在哪里?
补充:
我在主界面直接放置了两个自定义组件:GameView和CDiceAnimation

部分代码:
GameUIActivity

public class GameUIActivity extends AppCompatActivity implements Handler.Callback {
Handler mMainHandler;
Handler mGameHandler;
GameView mGameView;
GameDesk mGameDesk;
CDiceAnimation mDice;
@Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case MessagesDefine.DICE_HIDE://隐藏骰子
mDice.setVisibility(View.INVISIBLE); break;
case MessagesDefine.DICE_SHOW:
mDice.setVisibility(View.VISIBLE);
case MessagesDefine.GAME_DISPLAY_DESK:
if (mGameDesk.mGameState == GameState.PrepareGame){
mGameView.invalidate();
}
break;
}
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_ui);
mGameView = (GameView) findViewById(R.id.gameDisplayView);
mDice = (CDiceAnimation) findViewById(R.id.imageViewAnim);
InitGame();
}
void InitGame(){
mMainHandler = new Handler( this);
mGameDesk = new GameDesk(this);
mGameView.mGameDesk = mGameDesk;
…………
mDice.mThread = new Thread(mDice);
mDice.mThread.start();
mGameDesk.start(); //准备游戏线程
mGameHandler = new Handler(mGameDesk);
mGameHandler.sendEmptyMessage(MessagesDefine.GAME_START); //游戏开始
}
}

CDiceAnimation

public class CDiceAnimation extends ImageView implements Runnable,Handler.Callback{
Handler mDiceHandler;
GameDesk mGameDesk;
public int mResult; //最后返回的结果
int mRand1,mRand2;//两个骰子显示的数字,他们的和为最总的结果 mResult;
Thread mThread;
Handler mUIHandler;

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBitmapDice == null) return;
canvas.drawBitmap(mBitmapBuffer,0,0,null);
}

@Override
public void run() {
Looper.prepare();
mDiceHandler = new Handler(this);
Looper.loop();
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case MessagesDefine.DICE_SET_PLAYER:
mResult = 0;
new Thread(new Runnable() {
@Override
@SuppressWarnings("unchecked")
public void run() {
Log.w("Dice","开始扔骰子,起庄");
mCanvas.drawText("起 庄",mScreenWidth * 4/9,mScreenHeight * 5/14,mPaint);
startDice();
Log.w("Dice","起庄结果:mResult = " + mResult);
try {
//向阻塞队列中 压入结果CGameDesk中定义:public LinkedBlockingQueue mDiceResult
//下面这句会有个警告unchecked call to add(E),怎么处理一下?
mGameDesk.mDiceResult.put(mResult);
}catch (InterruptedException ie){
Log.e("Dice","出错,阻塞队列已满");
}
mGameDesk.mGameHandler.sendEmptyMessage(MessagesDefine.GAME_SET_FIRST_PLAYER);
}
}).start();
break;
}
return false;
}
public void startDice(){
mUIHandler.sendEmptyMessage(MessagesDefine.DICE_SHOW
…… //改变位置、载入位图资源、绘制到缓存位图,定时更新缓存位图postInvalidate();
mResult = mRand1 + mRand2 + 2; //最后的结果,两个骰子的和
mUIHandler.sendEmptyMessage(MessagesDefine.DICE_HIDE);
}
}

GameDesk

public class GameDesk extends Thread implements Handler.Callback {
public CDiceAnimation mDice; //骰子
public LinkedBlockingQueue mDiceResult = new LinkedBlockingQueue(1); //阻塞队列,同步数据
public Handler mGameHandler;
public Handler mMainHandler;
private GameUIActivity mGameUIActivity;
@Override
public boolean handleMessage(Message msg) {
switch (msg.what){
case MessagesDefine.GAME_START:
PrepareGame(); break;
case MessagesDefine.GAME_SET_FIRST_PLAYER:
SetTheFirstPlayer(); break;
case MessagesDefine.GAME_SET_FIRST_MJ:
SetTheFirstMJ(); break;
}
return false;
}
private void SetTheFirstPlayer(){// 设定庄家
Log.e("GameDesk","SetTheFirstPlayer");
int iRet = 0 ;
try {
iRet = (int) mDiceResult.take();
}catch (InterruptedException ie){
ie.printStackTrace();
}
try {
if (iRet == 0 ){
throw new Exception("骰子线程出错,没有返回结果");
}
}catch (Exception e){
Log.e("GameDesk","SetTheFirstPlayer中没有接受返回结果,骰子线程出错,没有返回结果");
}


if (mGameCount == 0 ){// 第一局
iRet = (iRet - 1) % 4;
mTheFirstPlayer = mPlayer[iRet];
}else {// 不是第一局
if (mContinueCount ==0) //没有连庄
mTheFirstPlayer = mTheFirstPlayer.mNext;
// else//连庄
// mTheFirstPlayer;//mTheFirstPlayer不变
}
Log.w("GameDesk","SetTheFirstPlayer 当前庄家:" + mTheFirstPlayer.mIndex +mTheFirstPlayer.mName);
try {
sleep(500);
}catch (InterruptedException ie){
ie.printStackTrace();
}
mDice.mDiceHandler.sendEmptyMessage(MessagesDefine.DICE_SET_FIRST_MJ);
}
private void SetTheFirstMJ(){
//略……
}

@Override
public void run() {
super.run();
Looper.prepare();
mGameHandler = new Handler(this);
Looper.loop();
}


}


public class GameView extends ImageView {
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mPaint == null)
mPaint = new Paint();
if (mDrawBuffer == null || mDrawBuffer.isRecycled())
mDrawBuffer = BitmapFactory.decodeResource(getResources(),R.drawable.bg1);
DrawMenuAndOther(canvas,mPaint);
if (mGameDesk.mGameState == GameState.DrawDesk ){
DrawAllUnitInOrder(canvas,mPaint);//绘制桌面
//mGameDesk.mGameHandler.sendEmptyMessage(MessagesDefine.GAME_SET_FIRST_PLAYER);
mDice.mDiceHandler.sendEmptyMessage(MessagesDefine.DICE_SET_PLAYER); //开始骰子动画
}
if (mGameDesk.mGameState == GameState.DispatchMJ){
DrawInDispatch(canvas,null);
}

}
}
...全文
726 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
xzx983 2018-04-17
  • 打赏
  • 举报
回复
引用 2 楼 z979451341 的回复:
我就加个状态改变就好了

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mPaint == null)
            mPaint = new Paint();
        if (mDrawBuffer == null || mDrawBuffer.isRecycled())
            mDrawBuffer = BitmapFactory.decodeResource(getResources(),R.drawable.bg1);
        DrawMenuAndOther(canvas,mPaint);
        if (mGameDesk.mGameState == GameState.DrawDesk ){
            DrawAllUnitInOrder(canvas,mPaint);
            //mGameDesk.mGameHandler.sendEmptyMessage(MessagesDefine.GAME_SET_FIRST_PLAYER);
            mDice.mDiceHandler.sendEmptyMessage(MessagesDefine.DICE_SET_PLAYER);
            mGameDesk.mGameState = GameState.DispatchMJ;

        }
        if (mGameDesk.mGameState == GameState.DispatchMJ){
            DrawInDispatch(canvas,null);
        }

    }
难道说,GameView的dispatchDraw执行了两次?所以dice开了两个线程? 那么绘制的时机在哪里啊 老大,会不会是,在界面上Dice覆盖了GameView会造成这个结果吗?
xzx983 2018-04-17
  • 打赏
  • 举报
回复
难道说,GameView的dispatchDraw执行了两次?所以dice开了两个线程? 那么绘制的时机在哪里啊
键盘舞者113 2018-04-17
  • 打赏
  • 举报
回复
我就加个状态改变就好了

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mPaint == null)
            mPaint = new Paint();
        if (mDrawBuffer == null || mDrawBuffer.isRecycled())
            mDrawBuffer = BitmapFactory.decodeResource(getResources(),R.drawable.bg1);
        DrawMenuAndOther(canvas,mPaint);
        if (mGameDesk.mGameState == GameState.DrawDesk ){
            DrawAllUnitInOrder(canvas,mPaint);
            //mGameDesk.mGameHandler.sendEmptyMessage(MessagesDefine.GAME_SET_FIRST_PLAYER);
            mDice.mDiceHandler.sendEmptyMessage(MessagesDefine.DICE_SET_PLAYER);
            mGameDesk.mGameState = GameState.DispatchMJ;

        }
        if (mGameDesk.mGameState == GameState.DispatchMJ){
            DrawInDispatch(canvas,null);
        }

    }
xzx983 2018-04-17
  • 打赏
  • 举报
回复
线程的lock与unlocked区域或者synchronized ()区域用invalidate()刷新界面,貌似OnDraw要等到 “ lock与unlocked区域或者synchronized () ”结束以后才会执行?

80,349

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧