参考:http://blog.csdn.net/lmj623565791/article/details/24015867。
2、如果有个100M大的文件,需要上传至服务器中,而服务器form表单最大只能上传2M,可以用什么方法。
个人理解:所谓表单最大只能上传2M,是不是指一个表单中附件只能上传最大2M,如果是的话,现在要求上传100M,为什么不直接
把附件上传大小设置为100M就可以了,除此菜鸟的我,并想不出这个题目究竟要考核面试者的什么知识点。
标准答案:这个问题不是很明确我觉得,首先来说使用http协议上传数据,特别在android下,跟form没什么关系。传统的在web中,在form中写文件上传,其实浏览器所做的就是将我们的数据进行解析组拼成字符串,以流的方式发送到服务器,且上传文件用的都是POST方式,POST方式对大小没什么限制。回到题目,可以说假设每次真的只能上传2M,那么可能我们只能把文件截断,然后分别上传了。
二次理解:因为android程序中页面都是活动和碎片,跟form没有什么关系,只有一个类似form的布局tablelayout,但跟form字面上都不是一回事,所以android并不存在form表单说法,应该是指html中form表单,那么表单附件上传中,首先把数据解析字符串,文件以IO流的方式上传到服务器,而且并没有上传限制,如果有话,应该是什么原因,防止长时间占用服务器,降低效率,那么把文件截断上传还有意义嘛,这个问题不具备普遍性,所以不进行深究。
3、内存溢出和内存泄漏有什么区别?何时会产生内存泄漏?内存优化有哪些方法?
个人理解:不知道他们的区别,以为是同一件事情,比如内存中创建的对象过多时,导致内容空间不够,会产生该现象;及时关闭不必要的
资源,如数据库连接、IO流等,另外可以通过代码重构,尽可能减少对象的创建数量。
标准答案:
内存溢出通俗理解就是软件(应用)运行需要的内存,超出了它可用的最大内存。
内存泄漏就是我们对某一内存空间的使用,使用完成后没有释放。
内存优化:Android中容易内存溢出的部分,就是图片的加载,我们可以使用图片的压缩加上使用LruCache缓存的目的来控制图片所能够使用的内存。还有对于比较耗资源的对象及时的关闭,例如Database Conn , 各种传感器, Service等等。
二次理解:内存溢出指内存超出它可用的最大内容,而内存泄露则特指使用的资源没有释放,而内容中容易内存溢出的就是存储加载,使用压缩和缓存的方式,而内存泄露则需要及时关闭资源,比如数据连接、服务等。概念话的内容,并没有实际的参照价值,因为暂时没有学习图片加载的使用
4、AsyncTask使用在哪些场景?它的缺陷是什么?如何解决?
个人理解:AsyncTask也是一种多线程的通信机制,但是AsyncTask并不需要去创建新的线程,把需要的操作直接定义在该对象的方法中就可以了,具体什么方法忘记,在第一行代码因为学习的Handler机制所以并没有加深对AsyncTask的理解,至于它的缺陷和解决方式更是不清楚了。
标准答案:
AsyncTask 运用的场景就是我们需要进行一些耗时的操作,耗时操作完成后更新主线程,或者在操作过程中对主线程的UI进行更新。
缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程,缓冲队列已满时,如果此时向线程提交任务,将会抛出RejectedExecutionException。
解决:由一个控制线程来处理AsyncTask的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask继续处理。
二次理解:
AsyncTask与Handler机制类似,即异步消息处理机制,所谓异步,即是并行执行的意思,而多线程就是相互独立"同时"在运行,而AsyncTask相对与Handler机制的不同,他对Handler进行了封装,在使用时不需要走Handler的流程,直接在doInBackground()中定义相关方法,系统自动创建新子线程去执行。AsyncTask与Handler机制是功能是相似的,可以用来在子线程中更新UI,或者下载耗时比较久的操作,比如下载文件因为主线程页面响应,即一个操作点击后,页面针对该操作做出反应的时间过长,那么Android系统会认为是不友好的行为,该程序会直接崩溃。关于标准答案中AsyncTask可以维护一个长度为128的线程池,究竟是什么概念,我可以理解为可以容纳128线程嘛?但是我能想象到的就是手机App目前都是客户端本地的模式,即C/S模式,基本不存在一个用户在一个应用下打开128个下载内容,但不排除这个情况,然后执行5个工作线程的又是什么意思,与128是否冲突,还是概念上有什么差别(解答:所谓可以执行5个工作线程,长度为128的线程池,好比迅雷下载,你可以开启128个下载任务,但是它只支持5个任务正在下载,超出的任务将进入缓冲区域,只有当前5个任务完结时,才会从缓冲区域获取并执行新的任务,而超出128个任务时,则提示拒绝执行异常)。关于标准答案开辟一个子线程去监控线程缓冲区是否已满,如果满了,则让请求的线程的睡眠,但是睡眠的时间怎么设定?怎么实现线程缓冲区空闲时,睡眠停止的工作。暂时还没有找到更加详细资料。
使用介绍:由于本人对AsyncTask的使用没有更多的了解,所以这里会讲AsyncTask的简单介绍和使用办法。
特点1:AsyncTask,是一个抽象类,所以要使用必须要创建一个子类就继承它。
特点2:AsyncTask,必须指定三个泛型参数,所谓类的泛型参数,可以认为是java的一种指定类中所关联对象的具体类型做法,这种做法的意义就是可以限制或者是明确了对象类型的范围,可以让编译器根据定义的泛型更加明确判定到内部代码的正确性,这是解决程序执行时多态转型异常的一种手段。参数列表为<Params,Progress,Result>,分别指传入的参数,可以在后台任务中使用;可以选择在前台显示当前进度,这里指定进度单位;任务执行完毕后,如果需要对结果进行返回,则这里指定返回指的类型。
最简单的形式:class DownloadTask extendsAsyncTask<Void,Integer,Boolean>,见第一行代码,Void表示不传入参数。
特点3:AsyncTask方法介绍:
- onPreExecute:顾明思义,就是在执行子线程任务之前调用,不如我们要下载一个文件,可以在这里显示一个进度框,因为这是在主线程中执行的。
- doInBackground(Params):该方法就是后台操作的内容,系统会自动生成一个子线程去执行该方法中的内容,一些耗时的内容,比如下载一个文件的代码。该方法的参数和返回值类型和泛型中第二、三个相对应。因为这里是在子线程中执行的,如果需要对主线程中进度框更新,则需要调用publicProgress(Progress),该方法的调用自动引入第三个方法onProgressUpdate(Progress)的调用。
- onProgressUpdate(Progress),它的调用取决于doInBackground(Params)中是否调用了publicProgress(Progress)的方法,它的Progress参数也来源于publicProgress(Progress)中的参数,该方法其实就是在主线中去更新进度。
- onPostExcuteResult(Result),该方法将在doInBackground(Params)执行完毕后执行,其中Result参数也来源于doInBackground方法的返回值,该方法可以执行对主线程的中UI的操作,比如关闭onPreExecute中创建的进度框,提示文件下载完成等。
- excute(Params),在主线程创建这个AsyncTask子类的对象后,调用改方法,将启动异步执行的操作。
代码示例1:
UIActivity.xml
<pre name="code" class="java">package com.noodles.uipractice;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class UIActivity extends AppCompatActivity {
private TextView tv;
private Button btn;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ui);
tv = (TextView) findViewById(R.id.tv);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
btn = (Button) findViewById(R.id.send_text);
/**
* 4、给Button定义个点击事件,就是启动AsyncTask
* 其中execute的参数Params内容会自动传递给doInBackground的字符串数组类型的参数
*/
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MyAsyncTask().execute("http://www.baidu.com");
}
});
}
/**
* 1、在主活动中中定义一个内部类MyAsyncTask继承AsyncTask
* 当然也可以不以内部类的形式,比如单独定义一个类或者用匿名内部类
* 不觉哪种定义方式更具有优势,因为单独定义分离后而代码结构更加清晰。
* 而匿名内部类和内部类更加贴近业务一体性。
*/
class MyAsyncTask extends AsyncTask<String, Integer, String> {
/**
* 2、复写doInBackground方法,该方法会开辟一个子线程去执行其中的代码
* 一般都是进行一些耗时的操作,这里可以去获取百度首页的内容
* <p/>
* String... params形式的参数列表,可以看做String[] params
*/
@Override
protected String doInBackground(String... params) {
BufferedReader br = null;
try {
//首先把百度的首页地址www.baidu.com,封装成URL,就比如在浏览器中用键盘输入www.baidu.com
URL url = new URL(params[0]);
//调用URL的openConnnection方法,就好比在浏览器的点击了回车
URLConnection connection = url.openConnection();
//如果没有下面这行话,则默认是调用GZIP的压缩技术,getContentLength()返回的就是-1
connection.setRequestProperty("Accept-Encoding", "identity");
//connection.connect();
long Total = connection.getContentLength();
/* 建立连接以后,形成了socket通道,以IO流的方式形成数据的流转,所谓IO流可以看作是计算机
* 所有媒介进行数据流转的一种固定形式,只是刚好起了一个名字叫IO流。而我们建立连接后
* 默认是以get的方式想百度服务器请求数据,可以请求返回一个字节输入流,即InputStream,而我们知道,返回
* 的内容都是字符串,所有可以通过InputStreamReader,把字节流转换成字符流,因为java为字符流提供的方式
* 更加易用,同时java提供一个缓存区的BufferReader,本质就是数组,可以把单独的字符用大的容器装载后
* 再进行传输,这样减少了传输的回合,提高效率
*
*/
//调用connection的getInputStream可以获取服务器返回的字符流
InputStream inputStream = connection.getInputStream();
//调用InputStreamReader对象,可以把字节流转换为字符流
InputStreamReader isr = new InputStreamReader(inputStream);
//用BufferReader去装载字符流
br = new BufferedReader(isr);
//调用BufferedReader的方法,更便捷的获取请求的内容
//定义一个字符串变量用来接收BufferedReader的readLine方法读取的每一行数据
String line;
StringBuffer stringBuffer = new StringBuffer();
int count = 0;
while ((line = br.readLine()) != null) {
//读取的每一行数据都放在stringBuffer中
stringBuffer.append(line);
/**
* 5、对UI中已经定义的进度条进行更新,直接调用publishProgress方法
* 但是里面的参数类型必须和AsyncTask中声明的泛型一致,即Float
*/
count += line.length();
Integer value = (int) (count / (float) Total * 100);
publishProgress(value);
Thread.sleep(1000);
}
return stringBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//如果执行期间发生异常,则返回null
return null;
}
/**
* 3、复写onPostExecute,其中它的参数值来源于doInBackground的返回值
* 该方法可以更新主线程的UI,把返回的内容直接显示在主线程的TextView上
*/
@Override
protected void onPostExecute(String s) {
tv.setText(s);
Toast.makeText(UIActivity.this, "数据下载结束", Toast.LENGTH_SHORT).show();
}
@Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.noodles.uipractice" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".UIActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
点击前:
点击后:
总结:AsyncTask是Android提供另一种异步信息处理机制,明确的说就是多线程间的通讯,有别于Handler机制地方,它是Handler的封装所以在使用上面
更加的便捷,首先我们需要继承该类,复写里面的方法,必须复写就是doInBackground(Params),该方法会创建一个子线程去执行方法中代码,所以一般用来
执行耗时的操作,比如下载文件。然后我们需要创建该子类的对象,并调用execute(Params)方法,其中参数Params由外部传入,该参数会自动传入oInBackground(Params)的参数,并且在AsyncTask的第一个泛型参数Params指定它的类型,第二泛型参数progress是指AsyncTask在doInBackground(Params)方法中可以调用publishProgress(progress),需要指定具体类型的值progress,系统会转而调用onProgressUpdate(progress)同时传入该数值,这个方法可以对主线程的UI进行更新,一般是用作更新进度条。第三个参数Result,是指doInBackground(Params)方法执行后需要返回一个值,接着系统会调用onPostExecute(Result),并把返回指传入这个方法,这个方法是执行一些收尾工作,把信息反馈给用户,比如更新主线程的UI,告诉用户下载已经完成等。
参考内容:
见:【极客学院】-【网络通讯】-【异步任务处理】-【AsyncTask的使用方法】。
见:http://blog.csdn.net/liuhe688/article/details/6532519。