Android的事件处理
1 android事件处理概述
不论是桌面应用还是手机应用程序,面对最多的就是用户,经常需要处理用户的动作-------也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理。android提供了两套事件处理机制:
- 基于监听的事件处理
主要做法就是为Android界面组件绑定特定的事件监听器;android还允许在界面布局文件中为UI组件的android:onClick属性指定事件监听方法,该方式需要开发者在activity中定义该事件监听方法(该方法必须带有一个View类型的形参,该形参代表被单击的UI组件,当用户单击该组件时,系统将会激发android:onClick属性所指定的方法)
- 基于回调的事件处理
主要做法是重写android组件特定的回调方法,或者重写Activity的回调方法。(基于回调的事件处理可以用于处理一些具有通用性的事件(业务逻辑比较固定),某些特定事件处理,仍需事件监听机制。)
2 基于监听的事件处理
2.1 监听的处理模型
2.1.1 事件监听的处理模型中,主要涉及如下三类对象
- Event Source(事件源):事件发生场所,通常是指各个组件,如按钮、窗口、菜单等
- Event(事件):事件封装了界面组件上发生的特定事情,Event包含所发生事件的相关信息
- Event Listener(事件监听器):负责监听事件源所相关事件的发生,并对并对发生事件作出反应
2.1.2 事件处理流程图
2.1.3 基于监听的时间处理模型的编程步骤
- 获取普通界面组件的对象(事件源),即被监听对象
- 实现事件监听器类,该监听器类是一个特殊的java类,必须实现一个xxxListener接口
- 调用事件源的setXxxListener方法将监听对象注册给事件源
2.2 内部类作为事件监听器类
- 可以在当前父类中复用该监听器
- 可自由访问外部类的所有界面组件
2.3 外部类作为事件监听器类
2.3.1 该形式比较少见,主要有两点原因:
- 事件监听器对应于具体的组件,定义成外部类,不利于提高程序的内聚性
- 外部类不能够自由访问创建GUI界面类的组件,编程不够简洁
2.3.2 若某个监听器需要被多个GUI界面组件所共享,且主要是完成某种业务逻辑的实现,则可考虑外部类的形式
2.4 Activity本身作为监听器
直接用Activity本身作为监听器类,这种形式非常简洁,但这种做法有两个缺陷:
- 这种程序结构可能造成混乱,Activity的主要职责应该是完成界面初始化工作
- Activity类本身还要实现监听接口,显得结构臃肿
2.5 匿名内部类作为事件监听器
- 由于大部分时候事件处理器都没有什么复用价值,因此大部分都是一次性使用,故造成此方法为最常用方法
2.6 直接绑定到标签
- 该方法结构简洁
- 但是结构也相对比较固定,适用范围有限(只支持onClick)
3 基于回调的事件处理
3.1 回调机制与监听机制
- 事件监听机制是一种委托式的事件处理,事件源和事件监听器分离,事件源发生器特定的事件后,该事件交给事件监听器负责处理
- 基于回调的事件模型来说,事件源与事件监听器是统一的,事件发生后,还是又事件源本身负责处理
- 为了使组件自身处理事件,则必须为组件对象添加方法,方法无法动态添加,故预置处理接口,继承重写方法即可
3.2 android为所有GUI组件都提供了一些事件处理的回调方法,以View为例,该类包含以下方法:
- onKeyDown,当用户在该组件上按下某个按键时触发该方法
- onKeyLongPress,当用户在组件上长按某个按键时触发该方法
- onKeyShortcut,当一个键盘快捷事件发生时触发该方法
- onKeyUp,当用户在该组件上松开某个按钮时触发该方法
- onTouchEvent ,当用户在该组件上触发触摸屏事件时触发该方法
- onTrackballEvent,当用户在该组件上触发轨迹球屏事件时触发该方法
3.3 基于回调的事件传播
几乎基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件:
- 如果处理事件的回调方法返回true,表明该处理方法已经完全处理该事件,该事件不会传播出去
- 如果处理时间的回调方法返回false,则表明处理方法并未完全处理事件,该事件会传播出去,
- 事件触发顺序为:事件源监听处理器---->事件源本身回调函数----->事件源父组件(递归而上)
3.4 两种处理模型的区别
- 基于监听的事件模型分工更明确,事件源、事件监听分别有两个类分开实现,因此具有更好的可维护性
- Android的事件处理机制保证基于监听的事件监听器会被优先触发
3.5 示例
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal">
- <EditText
- android:id="@+id/address"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:hint="请填写收信号码"
- />
- <EditText
- android:id="@+id/content"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:hint="请填写短信内容"
- android:lines="3"
- />
- <com.example.penghuster.myfirstapp.MyButton
- android:id="@+id/send"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="发送" />
- </LinearLayout>
- import android.app.Activity;
- import android.content.Context;
- import android.os.Bundle;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- public class MainActivity extends Activity {
- EditText address;
- EditText content;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- address = (EditText) findViewById(R.id.address);
- content = (EditText) findViewById(R.id.content);
- MyButton btn = (MyButton) findViewById(R.id.send);
- btn.requestFocus();
- btn.setFocusableInTouchMode(true);
- btn.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View source, int value, KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- Log.v("--Listener--", "the keydown ");
- }
- return false;
- }
- });
- }
- public boolean onKeyDown(int keyCode, KeyEvent event){
- super.onKeyDown(keyCode, event);
- Log.v("--activity---", "ddd");
- return false;
- }
- }
- class MyButton extends Button{
- public MyButton(Context context, AttributeSet set){
- super(context, set);
- }
- public boolean onKeyDown(int keyCode, KeyEvent event){
- super.onKeyDown(keyCode, event);
- Log.v("MyButton", "the onKeyDown in MyButton");
- return false;
- }
- }
4 响应系统设置的事件
在开发Android应用时,有时可能需要让应用程序随系统设置而进行调整,比如判断屏幕方向、判断系统方向的方向导航设备等。除此之外,有时还需要让应用程序监听系统设置的更改,并作出响应。
4.1 Configuration类
4.1.1 简介
- Configuration类专门用于描述手机设备上的配置信息,包括用户特定的配置项、系统的动态配置
- Configuration类的对象构建:Configuration cfg = Activity.getResources().getConfiguration()
- Configuration对象提供常用的获取系统配置信息的属性:
- public float fontScale:获取当前用户设置的字体缩放因子
- public int keyboard:获取当前设备所关联的键盘类型。该属性可能返回如下值:KEYBOARD_NOKEYS/KEYBOARD_QWERTY/KEYBOARD_12KEY
- public int keyboardHidden:该属性返回一个boolean值用于标识当前键盘是否可用。该属性不仅判断系统的硬件键盘、也判断系统的软键盘。如果该系统的硬件键盘不可用,软件键盘可用,也会返回KEYBOARDHIDDEN_NO;只有当两者都不可用用时,才返回KEYBOARDHIDDEN_YES
- public Locale locale:获取当前用户的Local,国家地区
- public int mcc:获取移动信号的国家码
- public int mnc:获取移动信号的网络码
- public int navigation:判断系统上方向导航设备的类型。该属性可能返回值:NAVIGATION_NONAV(无导航)、NAVIGATION_DPAD(DPOR导航)、NAVIGATION_TRACKBALL(轨迹球导航)、NAVIGATION_WHEEL(滚轮导航)
- public int orientation:获取系统屏幕的方向,该属性可能返回值ORIENTATION_LANDSCAPE(横向屏幕)、ORIENTATION_PORTRAIT(竖向屏幕)、ORIENTATION_SQUARE(方形屏幕)
- public int touchscreen:获取系统触摸屏的触摸方式,该属性可能返回TOUCHSCREEN_NOTOUCH(无触摸屏)、TOUCHSCREEN_STYLUS(触摸笔式触摸屏)、TOUCHSCREEN_FINGER(接受手指的触摸屏)
4.1.2 重写onConfigurationChanged响应系统设置更改
如果程序需要监听系统设置的更改,则可以考虑重写Activity的onConfiguration(Configuration newConfig)方法,该方法是一个基于回调的事件处理方法,当系统设置发生更改时,该方法会被自动触发。在程序中,可以动态调用setRequestedOrientation(int)方法来修改屏幕方向
4.1.3 示例:监听屏幕方向改变
Mainfest.xml
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.penghuster.myfirstapp" >
- <uses-sdk
- android:maxSdkVersion="12"
- android:minSdkVersion="10" />
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:configChanges="orientation|screenSize"
- 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>
activity.java
- import android.app.Activity;
- import android.content.Context;
- import android.content.pm.ActivityInfo;
- import android.content.res.Configuration;
- import android.os.Bundle;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
- public class MainActivity extends Activity {
- EditText address;
- EditText content;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- address = (EditText) findViewById(R.id.address);
- content = (EditText) findViewById(R.id.content);
- MyButton btn = (MyButton) findViewById(R.id.send);
- btn.setOnClickListener(new View.OnClickListener() {
- public void onClick(View source) {
- Configuration cfg = getResources().getConfiguration();
- if (cfg.orientation == Configuration.ORIENTATION_LANDSCAPE)
- MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- if (cfg.orientation == Configuration.ORIENTATION_PORTRAIT)
- MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- }
- });
- }
- public void onConfigurationChanged(Configuration configuration) {
- super.onConfigurationChanged(configuration);
- String screen = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE ?
- "横向屏幕" : "竖向屏幕";
- Toast.makeText(this, "系统屏幕方向改变\n" + "修改后屏幕方向为:" + screen, Toast.LENGTH_LONG).show();
- }
- }
5 Handler消息传递机制
5.1 UI线程
- Android的UI操作并不是线程安全的,多线程操作可能导致线程安全
- android制定一条简单的规则:只允许UI线程修改Activity里的UI组件
- UI线程:当一个程序第一次启动时,Android会同时启动一条主线程(main thread),负责处理与UI相关的事件,并把相关的事件分发到对应的组件进行处理
- 问题:由于只允许UI线程修改Activity里的组件,导致新启动的线程无法动态改变界面组件的属性值,但实际开发中,往往需要让新启动的线程周期性地改变界面组件的属性值,这就需要借助Handler的消息传递机制
5.2 Handler类简介
5.2.1 Handler类的主要作用
- 在新启动的线程中发送消息
- 在主线程中获取、处理消息
5.2.2 handler类消息处理原理
- 通过回调方式来实现,重写Handler类中处理消息的方法
- 新线程的发送消息时,消息会发送到与之关联的MessageQueue
- Handler会不断从MessageQueue中获取并处理消息
5.2.3 Handler类包含如下方法用于发送、处理消息
- void handlerMessage(Message msg):处理消息的方法,该方法通常用于被重写
- final boolean hasMessages(int what, Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息
- 多个重载的Message obtainMessage():获取消息
- final boolean sendEmptyMessageDelayed(int what, long delayMillis):指定多少毫秒后发送空消息
- final boolean sendMessage(Message msg):立即发送消息
- final boolean sendMessageDelayed(Message msg, long delayMillis):指多少毫秒之后发送消息
5.3 Handler、Loop、MessageQueue的工作原理
5.3.1 相关组件介绍
- Message:Handle接收和处理的消息对象
- Looper:每个线程只能拥有一个Looper,其loop方法负责读取MessageQueue中的消息,读到消息之后会把消息交给发送该消息的Handler进行处理。Looper的构造器使用private修饰,表明程序员无法通过构造器创建Looper对象
- MessageQueue:消息队列,采用先进先出的方式管理Message。程序创建Looper对象时,会在他的构造器中创建Looper对象。
5.3.2 Looper对象的创建
由于Looper对象没有提供public构造器,但是Handler正常工作,必须要求当前线程中有一个Looper对象,为了保证当前线程中有Looper对象,可分以下两种情况:
- 主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,让后通过Handler来发送、处理消息
- 程序员自己启动的子线程,程序员必须自己调用Looper类的静态方法repare()创建一个Looper对象,并启动它
5.3.3 在新线程中使用Handler的步骤:
- 调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue
- 有了Looper之后,创建Handler子类的实例,重写HandleMessage()方法,该方法负责处理来自其他线程的消息
- 调用Looper的loop()方法启动Looper
5.3.4 示例:使用新线程计算质数
- import android.app.Activity;
- import android.content.Context;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
- import java.util.ArrayList;
- import java.util.List;
- public class MainActivity extends Activity {
- EditText address;
- EditText content;
- static final String UPPER_NUM = "upper";
- CalThread calThread;
- class CalThread extends Thread {
- public Handler mHandler;
- public void run(){
- Looper.prepare();
- mHandler = new Handler(){
- public void handleMessage(Message msg){
- if (msg.what == 0x123){
- int upper = msg.getData().getInt(UPPER_NUM);
- List<Integer> nums = new ArrayList<Integer>();
- outer:
- for (int i=2; i<=upper; i++){
- for (int j=2; j<=Math.sqrt(i); j++)
- if (i != 2 && i % j ==0)
- continue outer;
- nums.add(i);
- }
- Toast.makeText(MainActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
- }
- }
- };
- Looper.loop();
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- address = (EditText) findViewById(R.id.address);
- content = (EditText) findViewById(R.id.content);
- MyButton btn = (MyButton) findViewById(R.id.send);
- calThread = new CalThread();
- calThread.start();
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Message msg = new Message();
- msg.what = 0x123;
- Bundle bundle = new Bundle();
- bundle.putInt(UPPER_NUM, Integer.parseInt(address.getText().toString()));
- msg.setData(bundle);
- calThread.mHandler.sendMessage(msg);
- }
- });
- }
- }
6 异步任务
6.1 为了解决新线程不能更新UI组件的问题,android提供了如下几种解决方案。
- 使用Handler实现线程之间的通信
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
- AsyncTask异步任务
6.2 AsyncTask(异步任务)
- AsyncTask<>是一个抽象类,通常用于被继承,继承AsyncTask需要指定如下三个泛型参数:Params,启动任务执行的输入参数类型;Progress,后台任务完成的进度值的类型;Result,后台任务执行完成后返回的结果类型
6.3 使用AsyncTask的步骤:
- 创建AsyncTask的子类,并为三个泛型参数指定类型,如果某个参数不需要,则指定为Void
- 根据需要选择性实现如下方法
- doInBackground(Params):重写该方法就是后台线程将要完成的任务,该方法可以调用publishProgress(Progress values)方法更新任务执行进度
- onProgressUpdate(Progress values)在doInBackground中调用publishProgress更新进度后,将会触发该方法
- onPreExecute():该方法将在执行后台耗时操作前被调用,通常该方法用于完成一些初始化的准备工作,比如在界面上显示进度条等
- onPostExecute(Result result):该方法在doInBackground()完成后,系统自动调用,并将doInBackground的返回值传给Result参数
- 调用AsyncTask子类实例的execute()开始执行耗时任务
6.4 使用AsyncTask时必须遵守如下规则
- 必须在UI线程中创建AsyncTask的实例
- 必须在UI线程中调用AsyncTask的execute方法
- doInBackground(Params),onProgressUpdate(Progress values),onPreExecute(),onPostExecute(Result result)等方法都是由系统负责调用
- 每个AsyncTask只能被执行一次,多次调用将会引发异常
6.5 示例:使用异步任务下载
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.TextView;
- import java.io.BufferedReader;
- import java.io.InputStreamReader;
- import java.net.URL;
- import java.net.URLConnection;
- public class MainActivity extends Activity {
- TextView address;
- TextView content;
- class DownTask extends AsyncTask<URL, Integer, String> {
- ProgressDialog pDialog;
- int hasRead = 0;
- Context mContext;
- public DownTask(Context ctx) {
- mContext = ctx;
- }
- protected String doInBackground(URL... params) {
- StringBuilder sb = new StringBuilder();
- try {
- URLConnection conn = params[0].openConnection();
- BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(),
- "utf-8"));
- String line = null;
- while ((line = br.readLine()) != null) {
- sb.append(line + "\n");
- hasRead++;
- publishProgress(hasRead);
- }
- return sb.toString();
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- return null;
- }
- protected void onPostExecute(String result) {
- address.setText(result);
- pDialog.dismiss();
- }
- protected void onPreExecute() {
- pDialog = new ProgressDialog(mContext);
- pDialog.setTitle("任务执行中");
- pDialog.setMessage("任务执行中,敬请期待");
- pDialog.setCancelable(false);
- pDialog.setMax(202);
- pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- pDialog.setIndeterminate(true);
- pDialog.show();
- }
- protected void onProgressUpdate(Integer... values) {
- content.setText("已经读取了" + values[0] + "行!");
- pDialog.setProgress(values[0]);
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- address = (TextView) findViewById(R.id.address);
- content = (TextView) findViewById(R.id.content);
- MyButton btn = (MyButton) findViewById(R.id.send);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- DownTask task = new DownTask(MainActivity.this);
- task.execute(new URL("http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html"));
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- });
- }
- }
Android的事件处理的更多相关文章
- Android的事件处理机制详解(二)-----基于监听的事件处理机制
基于监听的事件处理机制 前言: 我们开发的app更多的时候是需要与用户的交互----即对用户的操作进行响应 这就涉及到了android的事件处理机制; android给我们提供了两套功能强大的处理机制 ...
- Android热插拔事件处理详解
一.Android热插拔事件处理流程图 Android热插拔事件处理流程如下图所示: 二.组成 1. NetlinkManager: 全称是NetlinkManager.cpp位于And ...
- 【Android】事件处理系统
linux输入子系统 Android是linux内核的,所以它的事件处理系统也在linux的基础上完成的. Linux内核提供了一个Input子系统来实现的,Input子系统会在/dev/input/ ...
- Android按键事件处理流程 -- KeyEvent
刚接触Android开发的时候,对touch.key事件的处理总是一知半解,一会是Activity里的方法,一会是各种View 中的,自己始终不清楚到底哪个在先哪个在后,总之对整个处理流程没能很好的把 ...
- Android的事件处理机制(一)------基于回调机制的事件处理
Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...
- Android的事件处理-android学习之旅(四十四)
androd事件处理简介 控制飞机移动的简单实例 package peng.liu.test; import android.app.ActionBar; import android.app.Act ...
- Android教材 | 第三章 Android界面事件处理(二)—— 杰瑞教育原创教材试读
编者按 JRedu 杰瑞教育原创系列教材将于年后与大家正式见面.为更好的借鉴读者意见,我们将会陆续地在博客园推出一系列教材试读.我们也热忱的欢迎广大博友与我们互动,提出宝贵意见. 本篇博客将推出教材 ...
- Android教材 | 第三章 Android界面事件处理(一)—— 杰瑞教育原创教材试读
前 言 JRedu Android应用开发中,除了界面编程外,另一个重要的内容就是组件的事件处理.在Android系统中,存在多种界面事件,比如触摸事件.按键事件.点击事件等.在用户交互过程中, ...
- Android Button事件处理
一般只需要处理按钮的点击事件就可以,但想让一个按钮处理多个事件,就得同时监听多个方法. OnClickListener 点击事件 OnLongClickListener 长按事件 OnTouchLi ...
随机推荐
- mpi冒泡排序并行化
一.实验目的与实验要求 1.实验目的 (1)学会将串行程序改为并行程序. (2)学会mpich2的使用. (3)学会openmp的配置. (4)mpi与openmp之间的比较. 2.实验要求 (1)将 ...
- SQL 两张结构一样的表合并查询 .
select * from table1 union all select * from table2 union all 是所有的都显示出来: select * from table1 union ...
- uboot源码整体框架
源码解压以后,我们可以看到以下的文件和文件夹: cpu 与处理器相关的文件.每个子目录中都包括cpu.c和interrupt.c.start.S.u-boot.lds. cpu.c:初始化CPU.设 ...
- 微软嵌入式WEC2013产品研讨会(深圳站---2013.10.16)
主要内容如下: 1. Windows Embedded Compact 2013面向的市场 主要面向工业自动化.医疗设备和零售行业这些市场,和物联网关系非常紧密. 2. Windo ...
- IT项目量化管理:细化、量化与图形化 与 中国IT项目实施困惑
IT项目开发和实施的组织先后在组织中引入项目管理模型的管理制度.流程和方法,但收入甚微.大量的IT项目依然面临着无休止的需求蔓延与频繁加班.项目工期失控.质量低下等典型的项目失控现象.对项目引入量化意 ...
- OneNote快捷键
转载自:http://onenoter.com/2013/04/5792 记录笔记和设置笔记格式 键入和编辑笔记 若要执行此操作 按 打开一个新的 OneNote 窗口. Ctrl+M 打开一个小的 ...
- Java面试题-并发框架
1. SynchronizedMap和ConcurrentHashMap有什么区别? 答:java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap.Conc ...
- poj 1328 Radar Installation(贪心)
题目:http://poj.org/problem?id=1328 题意:建立一个平面坐标,x轴上方是海洋,x轴下方是陆地.在海上有n个小岛,每个小岛看做一个点.然后在x轴上有雷达,雷达能覆盖的范 ...
- Hibernate事务与并发问题处理(乐观锁与悲观锁)
目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hi ...
- APK中java代码反编译
Android APK中的Java代码可以被反编译到什么程度主要看APK的加密程度. 第一种情况:无混淆无加密无加壳.直接利用Dex2jar和JD-GUI可把源码从APK里抠出来,代码逻辑清晰,基本上 ...