#UserDemo
Android 服务端与客户端网络通信的简单用户注册登录(MVP模式)
Android 多线程
1. Handler:和 UI 线程间传递消息.
Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象。
实现异步的流程是主线程启动 Thread(子线程),thread(子线程)运行并生成 Message,Looper(消息队列)获取 Message并传递给 Handler,
Handler 逐个获取 Looper 中的 Message,并进行UI变更。
Handler把 Message 压入消息队列有两大体系:Post 和 sendMessage
1. Post: Post允许把一个Runnable对象入队到消息队列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。
2. sendMessage: sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法 有:sendEmptyMessage(int)、sendMessage(Message)、 sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)。
注: 两种方式实质没有区别,Post只是传递一个Runnable对象后会去调用sendMessage方法传递消息
Message自带的有如下几个属性:
int arg1:参数一,用于传递不复杂的数据,复杂数据使用setData()传递。
int arg2:参数二,用于传递不复杂的数据,复杂数据使用setData()传递。
Object obj:传递一个任意的对象。
int what:定义的消息码,一般用于设定消息的标志。
对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者Handler.obtainMessage()获取。
Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是调用的Message.obtain()。
2. AsyncTask: android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程
1) AsyncTask定义了三种泛型类型 Params,Progress和Result。
a. Params 启动任务执行的输入参数,比如HTTP请求的URL。
b. Progress 后台任务执行的百分比。
c. Result 后台执行任务最终返回的结果,比如String。
2) 使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:
doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。 在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
3) 有必要的话你还得重写以下这三个方法,但不是必须的:
onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled() 用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:
a. Task的实例必须在UI thread中创建;
b. execute方法必须在UI thread中调用;
c. 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;该task只能被执行一次,否则多次调用时将会出现异常;
3. java IO流
a. InputStream、OutputStream :处理字节流的抽象类
InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.
OutputStream是字节输出流的所有类的超类,一般我们使用它的子类,如FileOutputStream等
b. InputStreamReader OutputStreamWriter :转换流,该流对象中可以对读取到的字节数据进行指定编码的编码转换
InputStreamReader 是字节流通向字符流的桥梁,它将 **字节流转换为字符流** .
OutputStreamWriter是字符流通向字节流的桥梁,它将 **字符流转换为字节流.**
c. BufferedReader BufferedWriter:缓冲流,提高对流的操作效率
该类型的流有一个特有的方法:readLine();一次读一行,到行标记时,将行标记之前的字符数据作为字符串返回,当读到末尾时,返回null
BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行,从字符输入流中读取文本,缓冲各个字符,从而 提供字符、数组和行的高效读取 。
BufferedWriter 由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
d. 数据流(DataInputStream/DataOutputStream): 该数据流可以方便地对一些 基本类型数据 进行直接的存储和读取,不需要再进一步进行转换,通常只要操作基本数据类型的数据,就需要通过DataStream进行包装
e. 打印流(PrintStream/PrintWriter
Print流只有输出流无输入流,PrintWriter和PrintStream分别针对字符字节
两个类提供了重载的Print和Println方法用于多种数据类型的输出
PrintWriter和PrintStream的输出操作不会抛出异常
PrintWriter和PrintStream有自动flush功能
PrintWriter向文本输出流打印对象的格式化表示形式
PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
4. String、StringBuffer与StringBuilder之间区别
a. 三者在执行速度方面的比较:
StringBuilder > StringBuffer > String
b. 变与不变
String:字符串常量
StringBuffer:字符创变量
StringBuilder:字符创变量
c. 线程是否安全
StringBuilder:线程非安全的
StringBuffer:线程安全的
String:线程安全的
d. 使用总结
如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
5. Android网络编程之 Http通信
a.Get与Post请求区别:
Post请求可以向服务器传送数据,而且数据放在HTML HEADER内一起传送到服务端URL地址,数据对用户不可见。而get是把参数数据队列加到提交的URL中,值和表单内各个字段一一对应, 例如(http://www.baidu.com/s?w=%C4&inputT=2710)
get 传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
get安全性非常低,post安全性较高。
b.HttpURLConnectionction 继承于URLConnection类,二者都是抽象类。其对象主要通过URL的 openConnection 方法获得
HttpURLConnection默认使用GET方式 ,例如下面代码所示:
//使用HttpURLConnection打开连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//得到读取的内容(流)
InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
// 为输出创建BufferedReader
BufferedReader buffer = new BufferedReader(in);
String inputLine = null;
//使用循环来读取获得的数据
while (((inputLine = buffer.readLine()) != null))
{
//我们在每一行后面加上一个"\n"来换行
resultData += inputLine + "\n";
}
//关闭InputStreamReader
in.close();
//关闭http连接
urlConn.disconnect();
使用POST方式,则需要setRequestMethod设置 。代码如下:
// 使用HttpURLConnection打开连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//设置输入和输出流,post请求,设立需要设置为true
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
//设置请求方式为POST
urlConn.setRequestMethod("POST");
//POST请求不能使用缓存
urlConn.setUseCaches(false);
//是否应该自动执行 http 重定向
urlConn.setInstanceFollowRedirects(true);
// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
// 要注意的是connection.getOutputStream会隐含的进行connect。
urlConn.connect();
//DataOutputStream流
DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());
//要上传的参数
String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");
//将要上传的内容写入流中
out.writeBytes(content);
//刷新、关闭
out.flush();
out.close();
c.HttpClient接口: 使用Apache提供的HttpClient接口同样可以进行HTTP操作
GET方法 的操作代码示例如下:
// http地址
String httpUrl = "http://192.168.1.110:8080/httpget.jsp?par=HttpClient_android_Get";
//HttpGet连接对象
HttpGet httpRequest = new HttpGet(httpUrl);
//取得HttpClient对象
HttpClient httpclient = new DefaultHttpClient();
//请求HttpClient,取得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
//请求成功
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
//取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
mTextView.setText(strResult);
}
else
{
mTextView.setText("请求错误!");
}
}
使用 POST方法 进行参数传递时,需要使用 NameValuePair来保存要传递的参数 。,另外,还需要设置所使用的字符集。代码如下所示:
// http地址
String httpUrl = "http://192.168.1.110:8080/httpget.jsp";
//HttpPost连接对象
HttpPost httpRequest = new HttpPost(httpUrl);
//使用NameValuePair来保存要传递的Post参数
List params = new ArrayList();
//添加要传递的参数
params.add(new BasicNameValuePair("par", "HttpClient_android_Post"));
//设置字符集
HttpEntity httpentity = new UrlEncodedFormEntity(params, "gb2312");
//请求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)
{
//取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
mTextView.setText(strResult);
}
else
{
mTextView.setText("请求错误!");
}
}
6. 基于android的Socket通信
Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于, http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求
ServerSocket:
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(54321);
while (true)
{
//接受客户端请求
Socket client = serverSocket.accept();
System.out.println("accept");
try
{
//接收客户端消息
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String str = in.readLine();
System.out.println("read:" + str);
//向服务器发送消息
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(client.getOutputStream())),true);
out.println("server message");
//关闭流
out.close();
in.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
finally
{
//关闭
client.close();
System.out.println("close");
}
}
ClientSocket:
Socket socket = null;
String message = mEditText.getText().toString() + "/r/n";
try
{
//创建Socket
socket = new Socket("10.14.114.127",54321); //IP:10.14.114.127,端口54321
//向服务器发送消息
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
out.println(message);
//接收来自服务器的消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = br.readLine();
if ( msg != null )
{
mTextView.setText(msg);
}
else
{
mTextView.setText("数据错误!");
}
//关闭流
out.close();
br.close();
//关闭Socket
socket.close();
}
catch (Exception e)
{
// TODO: handle exception
Log.e(DEBUG_TAG, e.toString());
}
}
7. JSON数据解析
a.android: json
JSONObject:可以看作是一个json对象
JSONArray:可以看作是json的数组
b.android:使用Gson解析解析json
使用Gson包:com.google.gson.stream.JsonReader
下载地址:http://code.google.com/p/google-gson/downloads/list
文档Docs:http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html
String jsonData = "{\"username\":\"arthinking\",\"userId\":001}";
Gson gson = new Gson();
User user = gson.fromJson(jsonData, User.class);
c.fastjson
//json转对象
Student student=JSON.parseObject(json,Student.class);