Day05 数据存储及多线程断点续传
1.数据提交到服务器两种方式的优缺点
* GET请求
优点:使用非常方便,只需要在url后面组拼数据。
缺点:数据在url的后面组拼,不安全。有数据长度限制。
* POST请求
优点:安全,数据不是在url后面组拼而是通过流的方式写给服务器。数据长度不受限制
缺点:编写麻烦。
2.数据提交
* GET请求
1. 需要在url后面组拼提交的数据
* POST请求
1. 不需要组拼任何的数据
2. 必须指定请求的数据类型,是一个经过url编码的表单数据。Content-Type
3. 以流的方式把数据写给服务器,所以必须指定提交数据的长度。Content-Length
重要方法:设置给服务器写的数据的长度:conn.setRequestProperty("Content-Length", String.valueOf(data.length()));
记得指定要给服务器写数据:conn.setDoOutput(true);
3.中英文乱码问题的解决及细节
Tomcat默认码表iso-8859-1
Tomcat如果发现字符串不识别,就默认采用本地码表
byte[] bytes = string.getBytes(String charsetName)
将字符串按指定的编码转化为byte数组,默认采用本地码表
new String(byte[] bytes, String charsetName)
将byte数组按指定的编码转化为字符串
//提交的数据中含有中文时,将字符串qq按照编码UTF-8进行编码
客户端
URLEncoder.encode(qq, "UTF-8");
服务端
String qq = request.getParameter("qq");//tomcat采用的编码是iso-8859-1
System.out.println("qq:"+new String(qq.getBytes("iso-8859-1"),"utf-8"));
4.httpclient
get请求
//1.打开浏览器
HttpClient client = new DefaultHttpClient();
//2.输入地址或者数据
HttpGet httpGet = new HttpGet(path);
//3.敲回车
HttpResponse response = client.execute(httpGet);
//获取状态码
int code = response.getStatusLine().getStatusCode();
post方式
//1.打开浏览器
HttpClient client = new DefaultHttpClient();
//2.输入地址或者数据
HttpPost httpPost = new HttpPost(path);
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("qq", qq));
parameters.add(new BasicNameValuePair("pwd", pwd));
httpPost.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));
//3.敲回车
HttpResponse response = client.execute(httpPost);
//获取状态码
int code = response.getStatusLine().getStatusCode();
5.async-http开源框架
GET请求
String path = "http://192.168.1.103:8080/web/LoginServlet?qq="+URLEncoder.encode(qq)+"&pwd="+URLEncoder.encode(pwd);
AsyncHttpClient client = new AsyncHttpClient();
client.get(path, new AsyncHttpResponseHandler()
POST请求
String path = "http://192.168.1.103:8080/web/LoginServlet";
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("qq", qq);
params.put("pwd", pwd);
client.post(path, params, new AsyncHttpResponseHandler()
请求成功调用onsuccess()方法 请求失败调用onFailure()方法
文件上传的时候
put添加的是一个file对象
6.多线程下载用到的重要的API
//1.在客户端本地创建一个空白文件,文件的大小跟服务器的一模一样
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
raf.setLength(length);
raf.close();
//3.第i个线程只取服务器中的某一段数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
InputStream is = conn.getInputStream();
//4.第i个线程取回数据后,从某个位置开始写入数据
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
raf.seek(startIndex);//每个线程写文件的开始位置都是不一样的.
保证同步使用synchronize代码块
使用FileOutputStream数据不一定每一次都写到存储设备里,有可能写到硬盘的缓存里,使用RandomAccessFile将模式设置为rwd,可以保证每次都将数据写到磁盘里
HttpUtils http = new HttpUtils();
//第一个参数:服务器地址
//第二个参数:要下载到哪里
//是否断点续传
//下载的一些回调函数
http.download(path, "/mnt/sdcard/xxx.exe", true, new RequestCallBack<File>()
//下载成功的回调:onSuccess(ResponseInfo<File> arg0)
//进度更新的回调:onLoading(long total, long current, boolean isUploading)
//下载失败的回调:onFailure(HttpException arg0, String arg1)
day06activity
1、Android中开发一个界面的过程
界面在Android中对应的类为Activity
创建一个类继承Activity,在onCreate方法中通过setcontentView(R.layout.xxx)方法设置该界面的布局文件
在清单文件AndroidManifest.xml的application节点中配置该Activity
<activity
android:name="com.itheima.mutliuiapp.MainActivity" //配置类的全类名,必须配置
android:label="@string/app_name" > //标题栏上显示的文字,可以不配置
//应用程序的启动页面必须配置如下intent-filter节点,action和category缺一不可
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2.如何设置Activity没有标题栏
在清单文件中配置单个activity节点的主题
<activity
android:theme="@android:style/Theme.Light.NoTitleBar"
android:name="com.itheima.rpcalc.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节点的主题,在此配置后,该应用所有界面都没有标题栏
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
//1.找到主题对应的style文件,按住ctrl键用鼠标左键点击即可
android:theme="@style/AppTheme" >
...
...
</application>
//2.在对应的style文件中添加对应的条目
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:windowNoTitle">true</item>
</style>
在Activity的onCreate中设置
requestWindowFeature(Window.FEATURE_NO_TITLE);
3.如何进行界面的跳转?
显示意图
Intent intent = new Intent();//意图对象
intent.setClass(this, SecondActivity.class); //SecondActivity.class 要跳转到的界面
startActivity(intent);
如何关闭一个Activity
调用finish()方法
不要在主线程(UI线程)中使用Thread.sleep()方法,会让界面卡住
4.Activity 跳转时如何传递数据
第一个界面,传递数据
Intent intent = new Intent(this, ResultActivity.class);
//添加要传递的数据,可传递的数据类型有:
//1. 8个基本数据类型及其数组:byte、short、int、long、float、double、boolean、char及他们的数组
//2. 字符串及其数组:CharSequence及其数组、String及其数组
//3. 集合:CharSequence的ArrayList、String的ArrayList、Integer的ArrayList
//4. 对象:Serializable、Parcelable及其数组、继承自Parcelable的ArrayList
intent.putExtra(key,value);
startActivity(intent);
第二个界面,接收数据
//获取传递过来的数据
Intent intent = getIntent();
intent.getXXXExtra();
5.显式意图&隐式意图
显式意图,必须要指定被开启的Activity的类名或者路径名。激活自己应用程序内部的组件,推荐使用显式意图,效率高
Intent intent = new Intent();
intent.setClassName("com.itheima.twointent", "com.itheima.twointent.Activity01");
startActivity(intent);
隐式意图,只需要指定action(动作) 和 data (数据)就可以了。一般用来激活别的应用程序的界面,或者是自己应用程序的某个界面需要暴露给别的应用程序调用,效率低.
Intent intent = new Intent();
intent.setAction("com.itheima.twointent.OPEN02");
intent.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
Activity若想被隐式意图激活,需要配置意图过滤器
<activity android:name="com.itheima.twointent.Activity02">
<intent-filter >
<action android:name="com.itheima.twointent.OPEN02"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
6.隐式意图的详细参数
Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。
setData()和setType()要一起使用时,要使用setDataAndType()方法
7.打开系统应用某个界面的思路
找到该应用源码
在logcat中查看该界面是哪个Activity
在源码的清单文件中查找该Activity,查看其隐式意图
利用隐式意图激活该Activity
8.ListView条目的点击事件
lv.setOnItemClickListener(new OnItemClickListener() {
//当listview的条目被点击的时候调用的方法
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//parent:该ListView
//view:该行的View
//position:点击的是第几行,从0开始
}
});
9.开启另一个Activity获取数据的步骤
前提:A开启B,想从B获取数据
A调用startActivityForResult
Intent intent = new Intent(this, ContactListActivity.class);
startActivityForResult(intent, 2);
B界面设置数据
//把当前界面的数据,返回给开启我的界面.
Intent data = new Intent();
data.putExtra("message", message);
setResult(0, data);
//把当前界面关闭
finish();
返回A界面,系统会调用onActivityResult()方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
System.out.println("我们开启的新的选择短信的界面被关闭了,结果数据返回到这里");
if (data != null) {
String message = data.getStringExtra("message");
et_message.setText(message);
}
}else if(requestCode == 2) {
System.out.println("我们开启的新的选择联系人界面被关闭了,结果数据返回到这里");
}
super.onActivityResult(requestCode, resultCode, data);
}
10.请求码与结果码
请求码:如果A中多次调用startActivityForResult(),从其他界面获取数据,可以使用请求码进行区分
结果码:B中可以设置结果码,来通知A返回结果是否成功或其他信息
11.Activity的生命周期
对象从创建到被垃圾回收过程中一定会执行的方法就叫做生命周期方法.
onCreate 被创建
onDestroy 被销毁
onStart 可见
onStop 不可见
onResume 获取焦点
onPause 失去焦点
onRestart 界面不可见之后,再次回到该界面
12.生命周期的重要概念
entire lifetime
完整生命周期 oncreate--onstart--onresume--onpause--onstop--ondestroy
visible lifetime
可视生命周期 onstart--->onresume---onpause----ondestroy
foreground lifetime
前台生命周期 onresume ---> onpause
13.如何处理横竖屏切换
指定屏幕朝向
在清单文件对应的Activity中配置android:screenOrientation=”landscape”(横屏,portrait是竖屏);
设置屏幕旋转时不重新创建Activity
在清单文件对应的Activity中配置android:configChanges="keyboardHidden|orientation|screenSize",最好这三个都配置,否则不能适配所有机型或sdk版本。
横竖屏切换时会走Activity的onConfigurationChanged()方法
@Override
public void onConfigurationChanged(Configuration newConfig) {
// 当新设置中,屏幕布局模式为横排时
if(newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
//TODO 某些操作
}else{
//TODO 某些操作
}
super.onConfigurationChanged(newConfig);
14.任务栈
task stack
task: 一个应用程序一般包括多个Activity,每个Activity都是用来处理用户交互的一个任务
stack: 栈,是一总特殊的数据结构(后进先出)。队列要是一种特殊的数据结构(先进先出)
任务栈就是用来记录用户的操作的,记录的是Activity打开的先后顺序,后打开的界面先关闭,如果整个任务栈里面打开的Activity都被关闭了,就是应用程序被退出了.
一个应用程序一般只有一个任务栈,但是也可能对应有多个任务栈
15.Activity的启动模式
1.standard:标准的启动模式
默认应用场景
2.singleTop:单一顶部模式
如果Activity已经被开启,并且处于任务栈的栈顶,就不会创建新的Activity,而是复用这个已经开启的Activity。
为了防止出现一些奇怪的用户体验,推荐使用单一顶部模式,整个任务栈可以有多个实例存在.
应用场景:短信发送界面
3.singletask:单一任务栈
在整个任务栈里面只允许有一个当前Activity的实例存在
如果要开启的Activity在任务栈中已经存在,直接复用这个已经存在的Activity,并且把这个Activity上面的所有的其他Activity给清空
应用场景:如果一个Activity非常消耗内存和cpu资源,建议把这个Activity做成singletask的模式。浏览器的browserActivity
4.singleinstance:单一实例.
整个手机操作系统只有一个实例存在,并且是运行在自己单独的任务栈里面.
应用场景:通话界面的Activity