安卓事件机制

Andriod事件处理的方式

1.基于监听的事件处理
2.基于回调的事件处理

1. 基于监听的事件处理

1.1 监听的事件处理模型
Event Source:事件源,通常指事件发生的场所,即各个组件
Event:用户的一次操作
Event Listener:负责监听事件源发生的事件
该方式是委托式事件处理方式,组件将事件处理委托给监听器
在这里插入图片描述
1.2 实现方式
*

1)内部类作为监听器

public class MainActivity extends Activity
{ 
   public void onCreate(Bundle savedInstanceState)
	{
	...
   Button btn=findViewById(R.id.btn);
   btn.setOnClickListener(new clickListener());
   ...
   }
   class clickListener implements View.OnclickListener{
    ...
   }
   }
   无需传活动上下文对象给监听器,因为是内部类可以直接拿到。
  2)外部类作为监听器‘
  需要要传活动对象给外部类监听器

发短信案例:

public class MainActivity extends Activity
{
	EditText address;
	EditText content;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 获取页面中收件人地址、短信内容
		address = (EditText)findViewById(R.id.address);
		content = (EditText)findViewById(R.id.content);
		Button bn = (Button)findViewById(R.id.send);
		bn.setOnLongClickListener(new SendSmsListener( 
				this , address, content));
		if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS)!=
				PackageManager.PERMISSION_GRANTED){ //需要判断是否申请了权限
			ActivityCompat.requestPermissions(MainActivity.this,new String[]{
					Manifest.permission.SEND_SMS},1);
		}
	}
	@Override

	public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
		switch(requestCode){
			case 1:
				if(grantResults.length>0&&grantResults[0]!=PackageManager.PERMISSION_GRANTED){
					Toast.makeText(this,"你没有开启发短信权限",Toast.LENGTH_SHORT).show();
					finish();
				}
				break;
			default:
				break;
		}
	}
}
public class SendSmsListener implements OnLongClickListener
{
	private Activity act;
	private EditText address;
	private EditText content;
	public SendSmsListener(Activity act, EditText address
		, EditText content)
	{
		this.act = act;
		this.address = address;
		this.content = content;
	}
	@Override
	public boolean onLongClick(View source)
	{
		String addressStr = address.getText().toString();
		String contentStr = content.getText().toString();
		// 获取短信管理器
		SmsManager smsManager = SmsManager.getDefault();
		// 创建发送短信的PendingIntent
		PendingIntent sentIntent = PendingIntent.getBroadcast(act
				, 0, new Intent(), 0);
		// 发送文本短信
		smsManager.sendTextMessage(addressStr, null, contentStr
				, sentIntent, null);
		Toast.makeText(act, "短信发送完成", Toast.LENGTH_LONG).show();
		return false;
	}
}

     注册活动,允许启用相应权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.crazyit.event" >
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

  3)活动自身作为监听器
public class MainActivity extends Activity implements View.OnclickListener{
    ...
    btn.setOnClickListener(this);
    text.setOnClickListener(this);
    public void onClick(View v){
       switch(vid){
         case R.id.btn:
         //
         case R.id.text:
         //
         }
       
   }
   }

4)lambda表达式作为监听对象
btn.setOnClickListener(v->{
//具体处理
});
5)标定到标签
在活动布局文件中注册事件,在活动中复写对应事件处理方法

 <Button andriod:onClick="click"/>

2.事件回调

组件无需注册监听器,复写组件预置的监听事件处理方法
在这里插入图片描述

在这里插入图片描述
如果组件自身重写了事件处理方法①,且注册了事件处理器②,同时活动也复写了事件处理方法③,则事件捕获顺序为:①->②->③

3.响应系统设置的事件

在这里插入图片描述
在这里插入图片描述

4.利用Handler传递消息

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
两个案例:
1.计算质数(主线程向子线程发消息)
在这里插入图片描述
在这里插入图片描述
2.打地鼠,主线程自己收发消息

public class DiglettActivity extends AppCompatActivity implements View.OnClickListener,View.OnTouchListener{

    public  static final int CODE = 123;

    private TextView mResultTextView;
    private ImageView mDiglettImageView;
    private  Button mStarrButton;

    public int[][] mPosition = new  int[][]{
            {342,180},{432,880},
            {521,256},{429,780},
            {456,976},{145,665},
            {123,678},{564,567},
    };

    private  int mTotalCount;
    private  int mSuccessCount;

    public static final int MAX_COUNT = 10;

    private DiglettHandler mHandler = new DiglettHandler(this);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diglett);

        initView();

        setTitle("打地鼠");

    }

    private void initView(){
        mResultTextView = (TextView)findViewById(R.id.text_view);
        mDiglettImageView = (ImageView)findViewById(R.id.image_view);
        mStarrButton = (Button)findViewById(R.id.start_button);

        mStarrButton.setOnClickListener(this);
        mDiglettImageView.setOnTouchListener(this);
    }

    @Override
    public void onClick(View v){
        switch (v.getId()){
            case  R.id.start_button:
                start();
                break;
        }

    }
    private  void  start(){
        //发送消息 handler.sendmessagedelayer
        mResultTextView.setText("开始啦");
        mStarrButton.setText("游戏中.....");
        mStarrButton.setEnabled(false);
        next(0);
    }

    private  void  next(int delayTime){
        int position = new Random().nextInt(mPosition.length);

        Message message = Message.obtain();
        message.what =CODE;
        message.arg1 = position;

        mHandler.sendMessageDelayed(message,delayTime);
        mTotalCount ++;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.setVisibility(View.GONE);
        mSuccessCount ++ ;
        mResultTextView.setText("打到了"+ mSuccessCount +"只,共" + MAX_COUNT +"只.");
        return false;
    }

    public static class DiglettHandler extends Handler{
        public static final int RANDOM_NUBER = 500;
      public  final WeakReference<DiglettActivity> mWeakReference;

        public  DiglettHandler(DiglettActivity activity){
            mWeakReference = new WeakReference<>(activity);

        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            DiglettActivity activity = mWeakReference.get();

            switch (msg.what){
                case CODE:
                    if (activity.mTotalCount >MAX_COUNT){
                        activity.clear();
                        Toast.makeText(activity,"地鼠打完了!",Toast.LENGTH_LONG).show();
                        return;
                    }

                    int position = msg.arg1;
                    activity.mDiglettImageView.setX(activity.mPosition[position][0]);
                    activity.mDiglettImageView.setY(activity.mPosition[position][1]);
                    activity.mDiglettImageView.setVisibility(View.VISIBLE);

                    int randomTime = new Random().nextInt(RANDOM_NUBER) + RANDOM_NUBER;

                    activity.next(randomTime);
                    break;
            }
        }
    }
    private  void clear(){
        mTotalCount = 0;
        mSuccessCount = 0;
        mDiglettImageView.setVisibility(View.GONE);
        mStarrButton.setText("点击开始");
        mStarrButton.setEnabled(true);

    }
}

5.利用异步任务处理耗时任务

1.只有主线程可以对UI操作,因此当新线程处理完耗时任务之后,可使用如下方法处理UI:
在这里插入图片描述
在这里插入图片描述
2.使用异步任务
在这里插入图片描述
在这里插入图片描述
异步下载代码:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    public static final int INIT_PROGRESS = 0;
    public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
    public static final String FILE_NAME = "imooc.apk";
    private ProgressBar mProgressBar;
    private Button mDownloadButton;
    private TextView mResultTextView;

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

        // 初始化视图
        initView();

        // 设置点击监听
        setListener();

        // 初始化UI数据
        setData();
        private void initView() {

        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mDownloadButton = (Button) findViewById(R.id.button);
        mResultTextView = (TextView) findViewById(R.id.textView);

    }

    private void setListener() {

        mDownloadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO: 16/12/19 下载任务
                DownloadAsyncTask asyncTask = new DownloadAsyncTask();
                asyncTask.execute(APK_URL);
            }
        });
    }

    private void setData() {

        mResultTextView.setText(R.string.download_text);
        mDownloadButton.setText(R.string.click_download);
        mProgressBar.setProgress(INIT_PROGRESS);

    }


    /**
     * String 入参
     * Integer 进度
     * Boolean 返回值
     */
    public class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {
        String mFilePath;
        /**
         * 在异步任务之前,在主线程中
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // 可操作UI  类似淘米,之前的准备工作
            mDownloadButton.setText(R.string.downloading);
            mResultTextView.setText(R.string.downloading);
            mProgressBar.setProgress(INIT_PROGRESS);
        }

        /**
         * 在另外一个线程中处理事件
         *
         * @param params 入参  煮米
         * @return 结果
         */
        @Override
        protected Boolean doInBackground(String... params) {
            if(params != null && params.length > 0){
                String apkUrl = params[0];

                try {
                    // 构造URL
                    URL url = new URL(apkUrl);
                    // 构造连接,并打开
                    URLConnection urlConnection = url.openConnection();
                    InputStream inputStream = urlConnection.getInputStream();

                    // 获取了下载内容的总长度
                    int contentLength = urlConnection.getContentLength();

                    // 下载地址准备
                    mFilePath = Environment.getExternalStorageDirectory()
                            + File.separator + FILE_NAME;

                    // 对下载地址进行处理
                    File apkFile = new File(mFilePath);
                    if(apkFile.exists()){
                        boolean result = apkFile.delete();
                        if(!result){
                            return false;
                        }
                    }

                    // 已下载的大小
                    int downloadSize = 0;

                    // byte数组
                    byte[] bytes = new byte[1024];

                    int length;

                    // 创建一个输入管道
                    OutputStream outputStream = new FileOutputStream(mFilePath);

                    // 不断的一车一车挖土,走到挖不到为止
                    while ((length = inputStream.read(bytes)) != -1){
                        // 挖到的放到我们的文件管道里
                        outputStream.write(bytes, 0, length);
                        // 累加我们的大小
                        downloadSize += length;
                        // 发送进度
                        publishProgress(downloadSize * 100/contentLength);
                    }

                    inputStream.close();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            } else {
                return false;
            }

            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            // 也是在主线程中 ,执行结果 处理
            mDownloadButton.setText(result? getString(R.string.download_finish) : getString(R.string.download_finish));
            mResultTextView.setText(result? getString(R.string.download_finish) + mFilePath: getString(R.string.download_finish));

        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            // 收到进度,然后处理: 也是在UI线程中。
            if (values != null && values.length > 0) {
                mProgressBar.setProgress(values[0]);
            }
        }

    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值