Android 返回前面的Activity時且它也能自動更新

1 引用函數 setResult和 onActivityResult處理機制


   實現原理,在第二個Activity的返回事件中返回數據,第一個Activity中重構onActivityResult方法,在重構該方法的事件中,感受返回的數據,作出不一樣的處理。以達到自動更新第一個Activity的效應。詳細狀況參考以下的介紹。當前兩個activity,MainAcivity和SecondActivity;


A MainAcivity的重要代碼:


   public void onClick(View v) {
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, SecondActivity.class);
    Bundle bundle = new Bundle();
    Log.v("android.abc", "!!!!!"+MainActivity.this.toString());
    bundle.putString("uid", MainActivity.this.toString());
    intent.putExtras(bundle);
    startActivityForResult(intent,GET_CODE);
   }


B.SecondActivity中,在OnClickListener中
     findViewById(R.id.button).setOnClickListener(new View.OnClickListener() 
    {   
          @Override   
      public void onClick(View v) 
       {   
         setResult(RESULT_OK,(new Intent()).setAction(uid));   
         finish();   
       }   
   });  


  B.在MainActivity中,重寫onActivityResult方法;
   @Override   
   protected void onActivityResult(int requestCode, int resultCode, Intent data) 
   {   
    if(requestCode == GET_CODE)
    {   
     if(resultCode == RESULT_CANCELED)


      {   
        text2.setText("點擊了返回");   
      } 
      else 
      {   
        if (data != null) 


         {   
           text2.setText("獲得第二個activity返回的結果:\n"+data.getAction());   
          }   
      }   
    }   
  }  


其中static final private int GET_CODE = 0;是我自定義的常量,用來區分當前返回的是哪一個activity的結果;下面是類SecondActivity的代碼:
public class SecondActivity extends Activity{
String uid;
@Override
protected void onCreate(Bundle savedInstanceState)


{
      super.onCreate(savedInstanceState);
      setContentView(R.layout.second);
      Bundle bundle = this.getIntent().getExtras();
      if (bundle != null)
{
        uid = bundle.getString("uid");


       }
       findViewById(R.id.button).setOnClickListener(
new View.OnClickListener()
{
           @Override
           public void onClick(View v)
             setResult(RESULT_OK,(new Intent()).setAction(uid));
             finish();
           }
       });
    }
}


//


public void startActivityForResult (Intent intent, int requestCode)
   啓動一個Activity且傳遞一個requestCode值,在本Activity推出時,在啓動的Activity的onActivityResult()的方法中將會被調用到這個
傳遞的這個requestCode值。忽略這個requestCode值,實際上startActivityForResult跟startActivity(Intent)沒有什麼差異
 
注意,該方法只適用那些須要有一個返回值的Intent。在其餘協議(如ACTION_MAIN或ACTION_VIEW),你可能不會獲得當你指望的結果。舉個例子


,若是 你啓動的activity 採用了singleTask模式,它將不會運行在你的任務,所以你將收到一個取消的結果。做爲一種特殊的狀況下,在初始化


activity的onCreate(Bundle  savedInstanceState)/onResume() of your activity期間,若是你調用參數requestCode > = 0的


startActivityForResult(),那麼在窗口中將不會顯示返回來的結果,這是爲了在鏈接到另外一個activity時避免閃爍


protected void onActivityResult (int requestCode, int resultCode, Intent data)
 Called when an activity you launched exits, giving you the requestCode you started it with, the resultCode


it returned, and any additional data from it. The resultCode will be RESULT_CANCELED if the activity explicitly returned


that, didn't return any result, or crashed during its operation.


You will receive this call immediately before onResume() when your activity is re-starting.


Parameters
requestCode  The integer request code originally supplied to startActivityForResult(), allowing you to identify who this


result came from.
resultCode  The integer result code returned by the child activity through its setResult().
data  An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
//


 2 引用函數 onResume處理機制


在每個可能在改變語言區域的Activity 以前顯示出來的Activity中,重載onResume()並加入以下代碼:
oldLocale = mLocale;
Locale locale = getLocaleFormPreference(this);
if(oldLocale!=null && !oldLocale.equals(locale)) {
    Bundle bundle = new Bundle();


    activity.onSaveInstanceState(bundle);
    Intent intent = new Intent(this, this.getClass());
    intent.putExtra("InstanceState", bundle);
    intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
    startActivity(intent);
    finish();
}
並在onCreate(Bundle savedInstanceState)最後加入和動態更新時徹底相同的代碼。mLocale 其實是在onCreate(Bundle savedInstanceState)中,指定的Locale 時(也就是上一節最初時那段代碼)記住的。而若是,你的Activity啓動須要要一些原有Intent 的數據,別忘了自行導入


3 利用Handler刷新界面


Android提供了Invalidate方法實現界面刷新,可是Invalidate不能直接在線程中調用,由於他是違背了單線程模型:Android UI操做並非線程安全的,而且這些操做必須在UI線程中調用。實例化一個Handler對象,並重寫handleMessage方法調用invalidate()實現界面刷新;而在線程中經過sendMessage發送界面更新消息。


       // 在onCreate()中開啓線程
       new Thread(new GameThread()).start();、
       // 實例化一個handler
       Handler myHandler   = new Handler()
       {
              //接收到消息後處理
              public void handleMessage(Message msg)
              {
                     switch (msg.what)
                     {
                     case Activity01.REFRESH:
                            mGameView.invalidate();        //刷新界面
                            break;
                     }
                     super.handleMessage(msg);
              }                 
       };
 
       class GameThread implements Runnable
       {
              public void run()
              {
                     while (!Thread.currentThread().isInterrupted())
                     {
                            Message message = new Message();
                            message.what = Activity01.REFRESH;
                            //發送消息
                            Activity01.this.myHandler.sendMessage(message);
                            try
                            {
                                   Thread.sleep(100);
                            }
                            catch (InterruptedException e)
                            {
                                   Thread.currentThread().interrupt();
                            }
                     }
              }
       }


4  使用postInvalidate()刷新界面
   使用postInvalidate則比較簡單,不須要handler,直接在線程中調用postInvalidate便可。
       class GameThread implements Runnable


       {
              public void run()


              {
                     while (!Thread.currentThread().isInterrupted())


                     {
                            try


                            {
                                   Thread.sleep(100);
                            }
                            catch (InterruptedException e)
                            {
                                   Thread.currentThread().interrupt();
                            }
                            //使用postInvalidate能夠直接在線程中更新界面
                            mGameView.postInvalidate();
                     }
              }
       }


5 多線程和雙緩衝


 A.不使用多線程和雙緩衝
     這種狀況最簡單了,通常只是但願在View發生改變時對UI進行重繪。你只需在Activity中顯式地調用View對象中的invalidate()方法便可。系統會自動調用 View的onDraw()方法。
B.使用多線程和不使用雙緩衝
     這種狀況須要開啓新的線程,新開的線程就很差訪問View對象了。強行訪問的話會報:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.
     這時候你須要建立一個繼承了android.os.Handler的子類,並重寫handleMessage(Message msg)方法。android.os.Handler是能發送和處理消息的,你須要在Activity中發出更新UI的消息,而後再你的Handler(可使用匿名內部類)中處理消息(由於匿名內部類能夠訪問父類變量,你能夠直接調用View對象中的invalidate()方法)。也就是說:在新線程建立併發送一個Message,而後再主線程中捕獲、處理該消息。


Java代碼  


     new Thread(new Runnable() {  
         @Override  
        public void run() {  
              while(true){  
             try {  
.                  timeViewHandler.sendMessage(Message.obtain(timeViewHandler, MSG_UPDATE));  
                 Thread.sleep(1000);  
              } catch (InterruptedException e) {  
                  e.printStackTrace();  
              }   
          }  
     }  


  }).start();  




Java代碼  
        


      public class TimeViewHandler extends Handler {  
          private TextView timeView;  


     public TextView getTimeView() {  
          return timeView;  
      }  
    
     public void setTimeView(TextView timeView) {  
          this.timeView = timeView;  
      }  
      public TimeViewHandler(TextView timeView) {  
          super();  
         this.timeView = timeView;  
      }  


     @Override  
      public void handleMessage(Message msg) {  
          switch (msg.what) {  
              case MSG_UPDATE:  
                 timeView.setText(DateHelper.getNow("kk:mm:ss"));  
                  timeView.invalidate();  
                 break;  
          }  
         super.handleMessage(msg);  
.      }  
}  


C 使用多線程和雙緩衝


  Android中SurfaceView是View的子類,她同時也實現了雙緩衝。你能夠定義一個她的子類並實現SurfaceHolder.Callback接口。因爲實現SurfaceHolder.Callback接口,新線程就不須要android.os.Handler幫忙了。SurfaceHolder中lockCanvas()方法能夠鎖定畫布,繪製玩新的圖像後調用unlockCanvasAndPost(canvas)解鎖(顯示),仍是比較方便得。


Java代碼  
      public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback{  
          private SurfaceHolder holder;  
         private TouchDrawListener listener;  
          public TouchDrawListener getListener() {  
          return listener;  
      }  




     public void setListener(TouchDrawListener listener) {  
          this.listener = listener;  
      }  


      public TouchDrawView(Context context) {  
          super(context);  
          holder = getHolder();  
         holder.addCallback(this);  
         listener = new TouchDrawListener(holder);  
          listener.setShape(TouchDrawListener.SHAPE_LINE);  
          listener.setShape_style(TouchDrawListener.SHAPE_STYLE_FILL);  
          this.setOnTouchListener(listener);//設置屏幕事件監聽器  
         this.setLongClickable(true);//不設置將沒法捕捉onFling()事件  
          setFocusable(true);//設置鍵盤焦點  
.          setFocusableInTouchMode(true);//設置觸摸屏焦點  
      }  
      public TouchDrawView(Context context, AttributeSet as) {  
          this(context);  
      }  
      @Override  
      protected void onDraw(Canvas canvas) {    
      }  
     @Override  
     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
              int height) {  
     }  
     @Override  
      public void surfaceCreated(SurfaceHolder holder) {  
                   //關鍵部分  
          Canvas canvas = holder.lockCanvas(null);//獲取畫布    
         canvas.drawColor(Color.WHITE);//白色背景  
         holder.unlockCanvasAndPost(canvas);//解鎖畫布,提交畫好的圖像    
      }  
      @Override  
     public void surfaceDestroyed(SurfaceHolder holder) {  
      }  
  }   android

相關文章
相關標籤/搜索