Android的Handle
1:Handle与多线程
Handle是什么?官方说明:handle是Android给我们提供用来更新UI的一套机制,也是一套消息处理的机制。可以看出handle主要就是两个功能,一个是更新UI,另一个就是发送消息和对消息进行处理。
为什么要用Handle?
Handler是Thread的代言人,是多线程之间通信的桥梁,通过Handler,我们可以在一个线程中控制另一个线程去做某事。
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。 这个时候,Handler就出现了。,来解决这个复杂的问题 ,由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI
怎么用Handle机制?
public class MyHandlerActivity extends Activity { MyHandler myHandler; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myHandler = new MyHandler(); // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据 // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象 // (2): 让一个动作,在不同的线程中执行。 // 它安排消息,用以下方法 // post(Runnable) // postAtTime(Runnable,long) // postDelayed(Runnable,long) // sendEmptyMessage(int) // sendMessage(Message); // sendMessageAtTime(Message,long) // sendMessageDelayed(Message,long) // 以上方法以 post开头的允许你处理Runnable对象 //sendMessage()允许你处理Message对象(Message里可以包含数据,) MyThread m = new MyThread(); new Thread(m).start(); } /** * 接受消息,处理消息 ,此Handler会与当前主线程一块运行 * */ class MyHandler extends Handler { public MyHandler() { } public MyHandler(Looper L) { super(L); } // 子类必须重写此方法,接受数据 @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); // 此处可以更新UI Bundle b = msg.getData(); MyHandlerActivity.this.button.append(color); } } class MyThread implements Runnable { public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e。printStackTrace(); } Message msg = new Message(); Bundle b = new Bundle();// 存放数据 b.putString("color", "我的"); msg.setData(b); MyHandlerActivity。this。myHandler。sendMessage(msg); // 向Handler发送消息,更新UI } } }
2:json封装与解析
json数据类型表示:Object ,Array,String,number,true,false,null无其他使用key和value表示
{
"name":"xqc",
"age":25,
"birthday":"1997-07-21",
"major":["JAVA","Android","Python","前端"],
"work":null
}
json的使用 in java:
构建json对象:如果想查看,可以直接System.out.println(xqc.toString())即可
初级:
1 JSONObject xqc = new JSONObject(); 2 Object nullObj = null;//处理冲突 3 try{ 4 xqc.put("name","xqc"); 5 ...... 6 xqc.put("major",new String[]{"JAVA","Android","Python","前端"}); 7 xqc.put("work",nullObj); 8 9 }catch(JSONException e){ 10 e.printStackTrace(); 11 }
使用map构建:几乎与上边一样,只是先将对象存于Map,在调用json的构造方法转化为json对象
1 Map<String,Object> xqc = new HashMap<String,Object>(); 2 Object nullObj = null;//处理冲突 4 xqc.put("name","xqc"); 5 ...... 6 xqc.put("major",new String[]{"JAVA","Android","Python","前端"}); 7 xqc.put("work",nullObj); 11 new JSONObject(xqc);
使用javabean构建:开发中常用:先构建JAVABean对象,包含上述属性,生成get和set方法,然后:
1 Person xqc = new Person(); 2 xqc.setName("xqc"); 3 xqc.setMajor(new String[]{"JAVA","Android","Python","前端"}); 4 ...... 5 new JSONObject(xqc);
解析json
重文件读取json:将上述json数据存储在xqc.json文件中
1 File file = new File("xqc.json").getFile(); 2 String content = FileUtils.readFileToString(file); 3 JSONObject jsonObject = new JSONObject(content); 4 String name = jsonObject.getString("name"); 5 .....
Gson的使用
Gson生成json数据:与上述javabean几乎相同用法
1 Person xqc = new Person(); 2 xqc.setName("xqc"); 3 xqc.setMajor(new String[]{"JAVA","Android","Python","前端"}); 4 ...... 5 Gson gson = new Gson(); 6 gson.toJson(xqc);
Gson解析
1 File file = new File("xqc.json").getFile(); 2 String content = FileUtils.readFileToString(file); 3 Gson gson = new Gson(); 4 Person xqc = gson.fromJson(content,Person.class);//直接转换为person对象
3:BaseAdapter数据适配器
适配器顾名思义就是将数据源与控件进行合理匹配的一个class,最常见的就是ListView控件的使用
实现四个基本方法:
1 public class MyAdapter extends BaseAdapter { 2 // 映射数据 3 private List<ItemBean> myDataList; 4 //通过构造方法将数据源与适配器相关联 5 public MyAdapter(List<ItemBean> list) { 6 myDataList = list; 7 } 8 9 // 获取数据量 10 @Override 11 public int getCount() { 12 return myDataList.size(); 13 } 14 15 // 获取对应ID项对应的Item 16 @Override 17 public Object getItem(int position) { 18 return myDataList.get(position); 19 } 20 21 // 获取对应项ID 22 @Override 23 public long getItemId(int position) { 24 return position; 25 } 26 //获取每一项的具体数据内容内容 27 @Override 28 public View getView(int position, View convertView, ViewGroup parent) { 29 //实现最为复杂,三种实现方式下方介绍 30 }
为了不显得乱,这里就介绍一种开发中常用的: 避免重复findViewById的操作
private LayoutInflater mLayoutInflater; //初始化 public MyAdapter(Context context, List<ItemBean> list) { mLayoutInflater = LayoutInflater.from(context); } // ViewHolder用于缓存控件 class ViewHolder{ public ImageView img; public TextView title; public TextView content; } @Override public View getView(int position, View convertView, ViewGroup parent) { //创建内部类ViewHolder //判断convertView是否为空 //通过setTag将ViewHolder与convertView绑定 //getTag()取出关联的ViewHodle //通过ViewHolder对象周到对应的文件 ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); // 由于我们只需要将XML转化为View,并不涉及到具体的布局,所以第二个参数通常设置为null convertView = mLayoutInflater.inflate(R.layout.item, null); holder.img = (ImageView) convertView.findViewById(R.id.iv_image); holder.title = (TextView) convertView.findViewById(R.id.tv_title); holder.content = (TextView) convertView.findViewById(R.id.tv_content); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 取出bean对象/ ItemBean bean = mDataList.get(position); // 设置控件的数据 holder.img.setImageResource(bean.itemImageResid); holder.title.setText(bean.itemTitle); holder.content.setText(bean.itemContent); return convertView; }
4:网络通信
写在前面:千万不要忘了添加访问网络权限
<uses-permission android:name= "android.permission.INTERNET" />
Android网络编程分为两种:基于http协议的,和基于socket的。
基于Http协议:HttpClient、HttpURLConnection、AsyncHttpClient框架等
基于Socket:
(1)针对TCP/IP的Socket、ServerSocket
(2)针对UDP/IP的DatagramSocket、DatagramPackage
(3)Apache Mina框架
1.socket套接字:
socket通信的优点就是建立连接后服务器可以主动向客户端发送消息。Socket通信由IP地址和端口号两部分组成。通信时分为服务器端和客户端,在这里仅仅介绍客户端,在建立连接之前,服务器端会一直监听是否有连接的请求,当客户端Socket socket = new Socket(IPAdress, port);后建立连接,当然仅仅连接上是远远不够的,那怎么进行数据传输呐!其实还是用IO流进行传输
public class MainActivity extends Activity { private EditText editText; private Button button; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); editText = (EditText)findViewById(R.id.editText1); button = (Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Socket socket = null; String message = editText.getText().toString()+ "\r\n" ; try { //创建客户端socket,注意:不能用localhost或127.0.0.1,Android模拟器把自己作为localhost socket = new Socket("<span style="font-weight: bold;">10.0.2.2</span>",18888); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter (socket.getOutputStream())),true); //发送数据 out.println(message); //接收数据 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String msg = in.readLine(); if (null != msg){ editText.setText(msg); System.out.println(msg); } else{ editText.setText("data error"); } out.close(); in.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ try { if (null != socket){ socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }); } }
应用完成后一定要记得释放Socket对象
1 public static void Close() throws IOException{ 2 if(client!=null){ 3 client.close(); 4 } 5 }
2.http通信:http通信有两种实现方式,并且都有两种请求方式--get请求和post请求
HttpURLConnection的get请求:get一般用来请求url地址,一次请求一次响应,返回结果后就关闭连接
1 //get 2 public HttpURLConnection urlconn= null 3 URL url = new URL(urlStr); 4 //打开一个URL所指向的Connection对象 5 urlconn = (HttpURLConnection)url.openConnection(); 6 String result = StreamDeal(urlconn.getInputStream()); 7 urlconn.disconnect();
HttpURLConnection的post请求:post请求一般用于提交某些数据表单,所以使用POST时,就需要使用setRequestMothod()来设置请求方式了
URL url = new URL(urlStr); //打开一个URL所指向的Connection对象 urlconn = (HttpURLConnection)url.openConnection(); //设置该URLConnection可读 urlconn.setDoInput(true); //设置该URLConnection可写 urlconn.setDoOutput(true); //使用POST方式来提交数据 urlconn.setRequestMethod("POST"); //不运行缓存 urlconn.setUseCaches(false); //当使用POST方式进行数据请求时,我们可以手动执行connect动作,当然,这个动作其实在getOutputStream()方法中会默认执行的 //上面那些设置URLConnection属性的动作,一定要在connect动作执行前,因为一旦动作已经执行,熟悉设置就没有任何作用了 urlconn.connect(); //使用POST方式时,我们需要自己构造部分Http请求的内容,因此我们需要使用OutputStream来进行数据写如操作 OutputStreamWriter writer = new OutputStreamWriter(urlconn.getOutputStream()); String urlQueryStr = key+"="+URLEncoder.encode(value, "Utf-8"); writer.write(urlQueryStr); writer.flush(); writer.close(); //获取返回的内容 String result = StreamDeal(urlconn.getInputStream());
HTTPClient的get方式:
public String HttpGetMethod() { String result = ""; try { HttpGet httpRequest = new HttpGet(urlStr); HttpClient httpClient = new DefaultHttpClient(); HttpResponse httpResponse = httpClient.execute(httpRequest); if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK) { result = EntityUtils.toString(httpResponse.getEntity()); } else { result = "null"; } return result; } catch(Exception e) { return null; } }
HTTPClient的post请求:当我们使用POST方式时,我们可以使用HttpPost类来进行操作。当获取了HttpPost对象后,我们就需要向这个请求体传入键值对,这个键值对我们可以使用NameValuePair对象来进行构造,然后再使用HttpRequest对象最终构造我们的请求体,最后使用HttpClient的execute方法来发送我们的请求,并在得到响应后返回一个HttpResponse对象。其他操作和我们在HttpGet对象中的操作一样。
public String HttpPostMethod(String key,String value) { String result = ""; try { // HttpPost连接对象 HttpPost httpRequest = new HttpPost(urlStr); // 使用NameValuePair来保存要传递的Post参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); // 添加要传递的参数 params.add(new BasicNameValuePair(key, value)); // 设置字符集 HttpEntity httpentity = new UrlEncodedFormEntity(params, "Utf-8"); // 请求httpRequest httpRequest.setEntity(httpentity); // 取得默认的HttpClient HttpClient httpclient = new DefaultHttpClient(); // 取得HttpResponse HttpResponse httpResponse = httpclient.execute(httpRequest); // HttpStatus.SC_OK表示连接成功 if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 取得返回的字符串 result = EntityUtils.toString(httpResponse.getEntity()); return result; } else { return "null"; } } catch(Exception e) { return null; } }