天天看點

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:

android事件的處理非常重要,一個好的應用必定有很好的互動體驗。接下來我們就學習下android幾種事件處理的方式吧。

android有三種處理方式:

  • 基于事件的監聽。
  • 基于回調機制。
  • 基于控件的綁定。

    基于事件的監聽有四種方式:

  • 内部類
  • 匿名内部類
  • 外部類
  • 該類實作該接口
    接下來我們就一個一個講吧,并且會附上代碼。

内部類實作方式:

activity_main.xml布局檔案代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.androidforlistener.MainActivity">

  <Button
      android:id="@+id/btn"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="确定"/>
</LinearLayout>
           
裡面就一個按鈕,然後為按鈕聲明了一個id,我可以通過該id找到該控件。

MainActivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
  private Button mBtn;//聲明mBtn
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn= (Button) findViewById(R.id.btn);//初始化mBtn
       MyOnClickListener mListener=new MyOnClickListener();//初始化我們定義的事件
        mBtn.setOnClickListener(mListener);//為按鈕綁定事件
    }

    /*
    這就是内部類
     */
    class MyOnClickListener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            Toast.makeText(MainActivity.this,"",Toast.LENGTH_SHORT).show();
        }
    }
}
           

運作效果:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:

匿名内部類實作方式:

acitivity_main.xml布局檔案代碼跟上面的一樣,就不放出來了。

MainActivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
  private Button mBtn;//聲明mBtn
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn= (Button) findViewById(R.id.btn);//初始化mBtn
       /*
       setOnClickListener方法參數裡面接受一個
       OnClickListener接口參數。我們通過匿名類的方式傳遞一個OnClickListener參數
        */
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"我是通過匿名類實作的",Toast.LENGTH_SHORT).show();
            }
        });
    }
           

運作結果:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:

外部類實作方式:

acitivity_main.xml布局檔案代碼跟上面的一樣,就不放出來了。

MainActivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private Button mBtn;//聲明mBtn

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);//初始化mBtn
        MyOnClickLinstener mListener = new MyOnClickLinstener();//初始化mListener
        mBtn.setOnClickListener(mListener);//為mBtn綁定事件
    }
}

//這是外部類
class MyOnClickLinstener implements View.OnClickListener {

    @Override
    public void onClick(View v) {
        //這個會報錯,MainActivity.this,因為這是外部類不屬于該MainActivity中。我們就列印log吧
        //Toast.makeText(MainActivity.this,"我是通過外部類實作的",Toast.LENGTH_SHORT).show();
        Log.i("TAG", "我是通過外部類實作的..");
    }
}
           

運作結果:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:

該類實作該接口實作方式:

activity_main.xml布局檔案代碼跟上面的一樣,就不放出來了。

MainAcitivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

/*
MainActivity實作OnClickListener接口
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button mBtn;//聲明mBtn

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);//初始化mBtn
        mBtn.setOnClickListener(this);//為mBtn綁定事件
    }

    /*
    這是OnClickListener接口中的方法。
     */
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "我是實作OnClickListener接口", Toast.LENGTH_SHORT).show();
    }
}
           
android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
到這裡我們已經學完了四種基于監聽事件的處理。接下來就學習基于回調的。

基于回調機制的事件處理

首先我們要了解什麼是回調,不懂得可以參考我的另外一篇部落格

http://blog.csdn.net/song_shui_lin/article/details/51426595

看完了,基本知道什麼是回調。那我們就開始示範代碼吧。

首先我們先定義自己的view,MyButton代碼如下:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;

/**
 * Created by Administrator on 2016/9/21.
 */

public class MyButton extends Button {
    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("TAG", " MyButton 這個類中的onTouchEvent方法被執行。。。");

        //false代表的意思是該事件傳到這裡不截斷,還是向外抛
        return false;
    }
}
           

activity_main.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
    android:layout_width="match_parent" android:layout_height="match_parent"
   android:orientation="vertical"
    tools:context="com.example.edu.androidforlinstener.MainActivity">

    <com.example.edu.androidforlinstener.MyButton
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="确定"
        />
</LinearLayout>
           
可以看到,我們使用的是我們自己定義的MyButton,是包名加上你的類名才能使用

MainActivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    private MyButton mBtn;//聲明mBtn

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (MyButton) findViewById(R.id.btn);//擷取mBtn對象
        mBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.i("TAG", " 該按鈕觸摸事件被處理了。。。");

                //false代表的意思是該事件傳到這裡不截斷,還是向外抛
                return false;
            }
        });

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("TAG", " MainActivity 這個類中的onTouchEvent這個方法被被執行。。。");

        //false代表的意思是該事件傳到這裡不截斷,還是向外抛
        return false;
    }
}
           

運作結果:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
MyButton類中的onTouchEvent方法就是一個回調方法。。

基于控件的綁定事件處理

activity_main.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.edu.androidforlistener1.MainActivity">

   <Button
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="确定"
       android:onClick="onClick"/>
</LinearLayout>
           
這個布局檔案也很簡單,就一個按鈕,特别注意的是 android:onClick屬性值必須跟我們 方法名一樣,不然會報錯

MainActivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //方法名必須跟onClick屬性的值一樣
    public void onClick(View view) {

        Toast.makeText(MainActivity.this, "我是綁定控件實作的", Toast.LENGTH_SHORT).show();
    }
}
           

運作結果如下:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
到這裡我們已經學完了基本的android事件處理。。接下來我們再學習下Handler和 AsyncTask。這兩個我們也是必須掌握的。

Handler示範下簡單的使用。

首先我們就實作簡單的demo吧,就是從1加到100的過程。來學習下handler的使用

main_activity.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="0dp"
        android:text="确定" />

    <TextView
        android:id="@+id/number_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="0"
        android:textColor="#ff0000"
        android:textSize="28sp" />
</LinearLayout>
           
這個布局檔案就是一個按鈕和一個textview,

MainAcitivity.java代碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private Button mBtn;
    private TextView mTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);
        mTv = (TextView) findViewById(R.id.number_tv);
        //為按鈕添加點選事件
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = ; i < ; i++) {
                            mTv.setText("" + i);
                        }
                    }
                }).start();
            }
        });

    }
}
           
然後我們運作下,一點選按鈕,我們的程式就崩潰。看下錯誤日志,
android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
意思是說隻有主線程(ui線程)才能更改ui。是以我們這種方法不行。

MainAcitivity.java更改後代碼如下:

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private Button mBtn;
    private TextView mTv;
    int tempNumber;

    //定義一個hangler,并重寫了裡面的方法、
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (tempNumber == ) {
                Toast.makeText(MainActivity.this, "100完成", Toast.LENGTH_SHORT).show();
            }
            if (msg.what == ) {
                mTv.setText(tempNumber + "");
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);
        mTv = (TextView) findViewById(R.id.number_tv);
        //為按鈕添加點選事件
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = ; i < ; i++) {
                            tempNumber = i;
                            handler.sendEmptyMessage();
                            try {
                                Thread.sleep();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                        }

                    }
                }).start();
            }
        });

    }
}
           
這裡使用了handler機制來處理。我們通過在子線程發送一個消息,然後主線程收到消息後。就會處理這個消息。handler具體的知識現在在這裡就不講了,隻要記住一點。在子線程發送消息讓主線程來處理就好了。

運作結果如下:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
接下來我們就學習下AsyncTask。

AsyncTask

首先我們來看下官網對它的解釋:
android之事件處理/Handler/AsyncTaskandroid有三種處理方式:

第一句話就講AsyncTask enables proper and easy use of the UI thread.

AsyncTask 能夠恰當和容易地去使用ui線程。這是官網對AsyncTask詳細的解釋和使用步驟 ,通路這網站需要翻牆。不會翻的找我。嘎嘎。。。

https://developer.android.com/reference/android/os/AsyncTask.html

我們先建立自己的任務MyTask 代碼如下:

import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Created by Administrator on 2016/9/21.
 */

public class MyTask extends AsyncTask<Integer, Integer, String> {
    private TextView mTv;
    private Context mContext;

    public MyTask() {
    }

    public MyTask(TextView mTv, Context mContext) {
        this.mTv = mTv;
        this.mContext = mContext;
    }

    /*
    一般這個方法用來初始化工作
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

    }

    /*
    任務執行完然後調用,
     */
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Toast.makeText(mContext, s, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        mTv.setText(values[] + "");
    }

    /*
    這個方法是在子線程執行的。我們必須要實作的方法
     */
    @Override
    protected String doInBackground(Integer... params) {
        for (int i = ; i < ; i++) {
            publishProgress(i);//執行這個方法,會回調onProgressUpdate這個方法。
            try {
                Thread.sleep();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return "100完成";
    }
}
           

執行的順序:

android之事件處理/Handler/AsyncTaskandroid有三種處理方式:
畫圖工具畫的,感覺好醜。。。

MainAcitivity.java代碼如下:

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private Button mBtn;
    private TextView mTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);
        mTv = (TextView) findViewById(R.id.number_tv);
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyTask task=new MyTask(mTv,MainActivity.this);
                task.execute();
            }
        });

    }
}
           

運作效果跟handler一樣。不信運作一遍。。

到這裡我們已經學完了handler和AsyncTask知識了。跟着上面敲一遍,應該能學到點東西。。嘎嘎。

源碼下載下傳

https://github.com/songshuilin/AndroidForBlog/tree/master/androidforhandler