1.android的四大组件
在单例集合Collection中比较重要的就是list集合和set集合。
list集合是可重复的,有序的。其下有Arraylist(底层是数组结构)和LinekdList(底层是链表结构)用的比较多。还有一个效率比较低,安全的集合Vector被不安全的ArrayList取代了。
set集合是不可重复的,无序的。其下HashSet(哈希表,HashCode() ,equest()) 和 TreeSet(二叉树)。
Map中比较重要的HashTable(哈希表),HashMap(哈希表),TreeMap(二叉树)
IO流:
多线程:
线程的两种创建方式:
1>:继承Thread类
2>:实现Runnable接口
在实际开发过程中,一般开启一个线程都是指定实现某种特殊耗时操作的,由于该功能的单一性,一般情况下都会使用继承的方式来创 建该线程.
在android中,主线程由于直接和用户UI表现,因此android中不允许耗时的操作在主线程中执行的,所以要开启一个进行耗时操作的子线程来完成耗时操作,而子线程无法更改UI,因此在子线程耗时操作完成的时候就用到了Handlder通信机制来通知主界面来更改UI.
因此,在android中子线程的开启多半会伴随着Handler一同使用.
泛型:
泛型通俗点就是用一个通用的类型(比如T)来代替所有的类型.
由于在开发中增强代码的复用性,而某些方法如果指定具体的类型之后,再使用其他的类型就无法再调用该方法.而有了泛型之后就可以通过一个抽象的T来取代想要传入的参数类型,也就增强了代码的复用性.
比如有时候我们要用到adapter的时候,而该adapter需要适配多个list数据,而该list数据又是多种,那么此时如果书写多个adapter来针对专用的list就使得代码比较臃肿,因此用泛型来代替就可以很好的对程序进行简化,提高复用性.
5.集合和数组的区别
集合可以说是一个可变长度的数组,并且集合封装的数据类型是一个具体的对象类型.
在实际开发中,基本上都是使用集合来代替数组.
6.android中常用的布局?
FrameLayout,LinearLayout,AbsoluteLayout,RelativeLayout,TableLayout五种布局
但是最常用的是LinerLayout和RelativeLayout,FrameLayout有时候也用,其他两种基本不使用.
1>.Shared Preferences共享偏好
该存储方式存储一些基本数据类型数据,以key和value的形式来存储数据,一般开发中在app启动的时候会从服务器获取该用户的基本数据信息使用SharedPreferences存储起来,待后续访问网络获取数据的时候将用户参数提取出来进行服务器信息的访问.
2>本地file文件存储
相对较大量的数据比如协议等数据就可以以IO流的方式存入到本地file文件.
3> ContentProvider
Android系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个Content Provider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享时,就需要使用Content Provider为这些数据定义一个URI,然后其他的应用程序就通过Content Provider传入这个URI来对数据进行操作
publicclassMyDatabaseHelperextendsSQLiteOpenHelper{
publicstaticfinalString CREATE_BOOK ="create table book ("
+"id integer primary key autoincrement, "
+"author text, "
+"price real, "
+"pages integer, "
+"name text)";
privateContext mContext;
publicMyDatabaseHelper(Context context,String name,
CursorFactory factory,int version){
super(context, name, factory, version);
mContext = context;
}
@Override
publicvoid onCreate(SQLiteDatabase db){
// TODO Auto-generated method stub
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,"Create succeeded",Toast.LENGTH_SHORT).show();
}
@Override
publicvoid onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
// TODO Auto-generated method stub
}
}
privateclassMyTaskextendsAsyncTask<String,Integer,String>{
//onPreExecute方法用于在执行后台任务前做一些UI操作
@Override
protectedvoid onPreExecute(){
Log.i(TAG,"onPreExecute() called");
textView.setText("loading...");
}
//doInBackground方法内部执行后台任务,不可在此方法内修改UI
@Override
protectedString doInBackground(String... params){
Log.i(TAG,"doInBackground(Params... params) called");
try{
HttpClient client =newDefaultHttpClient();
HttpGet get =newHttpGet(params[0]);
HttpResponse response = client.execute(get);
if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
long total = entity.getContentLength();
ByteArrayOutputStream baos =newByteArrayOutputStream();
byte[] buf =newbyte[1024];
int count =0;
int length =-1;
while((length = is.read(buf))!=-1){
baos.write(buf,0, length);
count += length;
//调用publishProgress公布进度,最后onProgressUpdate方法将被执行
publishProgress((int)((count /(float) total)*100));
//为了演示进度,休眠500毫秒
Thread.sleep(500);
}
returnnewString(baos.toByteArray(),"gb2312");
}
}catch(Exception e){
Log.e(TAG, e.getMessage());
}
returnnull;
}
//onProgressUpdate方法用于更新进度信息
@Override
protectedvoid onProgressUpdate(Integer... progresses){
Log.i(TAG,"onProgressUpdate(Progress... progresses) called");
progressBar.setProgress(progresses[0]);
textView.setText("loading..."+ progresses[0]+"%");
}
//onPostExecute方法用于在执行完后台任务后更新UI,显示结果
@Override
protectedvoid onPostExecute(String result){
Log.i(TAG,"onPostExecute(Result result) called");
textView.setText(result);
execute.setEnabled(true);
cancel.setEnabled(false);
}
//onCancelled方法用于在取消执行中的任务时更改UI
@Override
protectedvoid onCancelled(){
Log.i(TAG,"onCancelled() called");
textView.setText("cancelled");
progressBar.setProgress(0);
execute.setEnabled(true);
cancel.setEnabled(false);
}
privatevoid parseXMLWithPull(String xmlData){
// TODO Auto-generated method stub
try{
XmlPullParserFactory factory =XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(newStringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String id ="";
String name ="";
String version ="";
while(eventType !=XmlPullParser.END_DOCUMENT){
String nodeName = xmlPullParser.getName();
switch(eventType){
// 开始解析某个节点
caseXmlPullParser.START_TAG:{
if("id".equals(nodeName)){
id = xmlPullParser.nextText();
}elseif("name".equals(nodeName)){
name = xmlPullParser.nextText();
}elseif("version".equals(nodeName)){
version = xmlPullParser.nextText();
}
break;
}
caseXmlPullParser.END_TAG:{
if("app".equals(nodeName)){
Log.d("MainActivity","id is"+ id);
Log.d("MainActivity","name is "+ name);
Log.d("MainActivity","version is "+ version);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
}catch(Exception e){
e.printStackTrace();
}
}
publicclassMyHandlerextendsDefaultHandler{
privateString nodeName;
privateStringBuilder id;
privateStringBuilder name;
privateStringBuilder version;
@Override
publicvoid startDocument()throwsSAXException{
//初始化容器,用来存放解析出来的数据。
id =newStringBuilder();
name =newStringBuilder();
version =newStringBuilder();
}
@Override
publicvoid endDocument()throwsSAXException{
// TODO Auto-generated method stub
super.endDocument();
}
@Override
publicvoid startElement(String uri,String localName,String qName,
Attributes attributes)throwsSAXException{
//记录当前节点名
nodeName = localName;
}
@Override
publicvoid endElement(String uri,String localName,String qName)
throwsSAXException{
if("app".equals(localName))
{
Log.d("MyHandler","id is "+ id.toString().trim());
Log.d("MyHandler","name is "+ name.toString().trim());
Log.d("MyHandler","version is "+ version.toString().trim());
//最后要将StringBuilder清空掉。
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
@Override
publicvoid characters(char[] ch,int start,int length)
throwsSAXException{
//根据当前的节点名判断将内容添加到哪一个StringBuilder对象中
if("id".equals(nodeName))
{
id.append(ch,start,length);
}elseif("name".equals(nodeName))
{
name.append(ch,start,length);
}elseif("version".equals(nodeName))
{
version.append(ch,start,length);
}
}
}
privatevoid parseXMLWithSAX(String xmlData){
// TODO Auto-generated method stub
try{
SAXParserFactory factory =SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
MyHandler handler =newMyHandler();
//将MyHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
xmlReader.parse(newInputSource(newStringReader(xmlData)));
}catch(Exception e)
{
e.printStackTrace();
}
}
/**
* 使用JSONObject
* @param xmlData
*/
privatevoid parseJSONWithJSONObject(String jsonData)
{
try{
JSONArray jsonArray =newJSONArray(jsonData);
for(int i =0; i < jsonArray.length(); i ++)
{
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
String version = jsonObject.getString("version");
Log.d("MainActivity","id is "+ id);
Log.d("MainActivity","name is "+ name);
Log.d("MainActivity","version is "+ version);
}
}catch(Exception e)
{
e.printStackTrace();
}
}
privatevoid parseJSONWithGSON(String jsonData)
{
Gson gson =newGson();
List<App> appList = gson.fromJson(jsonData,newTypeToken<List<App>>(){}.getType());
for(App app : appList)
{
Log.d("MainActivity","id is "+ app.getId());
Log.d("MainActivity","name is "+ app.getName());
Log.d("MainActivity","version is "+ app.getVersion());
}
}
measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:(1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。
2>、layout操作layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:(1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;(2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;
3>、draw操作draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作:(1)绘制背景;(2)如果要视图显示渐变框,这里会做一些准备工作;(3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法;(4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;(5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框;(6)绘制滚动条;从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。
publicclassSingleton{
privateSingleton(){}
privatestaticSingleton singleton =null;//不建立对象
publicstaticsynchronizedSingleton getInstance(){
if(singleton ==null){//先判断是否为空
singleton =newSingleton();//懒汉式做法
}
return singleton ;
}
publicclassSingleton{
publicSingleton(){}
privatestaticSingleton singleton =newSingleton();//建立对象
publicstaticSingleton getInstance(){
return singleton ;//直接返回单例对象 }}
补间动画:
通过父容器将其隐藏再不断的重绘来达到动画效果,其实view并没有改变。位移、旋转、缩放、渐变、 只能作用在View上面。
属性动画:
属性动画是3.0出现的,它不仅可以对view添加动画效果,还可以对对象添加动画效果和对动画进行拓展。
ValueAnimation: 对值进行一个平滑的动画过度。ObjectAnimation: 它可以直接对任意对象进行动画操作。他们都具备ofFloat()方法,因为ObjectAnimation是ValueAnimation的子类,只是方法的参数列表不一样。ObjectAnimation中的ofFloat()的第二个参数并不是根据传入的字符串进行解析,其内部是去寻找和其相关的get和set方法。
Bundle mBundle =newBundle();
mIntent.putExtras(mBundle);
// 调用浏览器
Uri webViewUri =Uri.parse("http://blog.csdn.net/zuolongsnail");
Intent intent =newIntent(Intent.ACTION_VIEW, webViewUri);
// 调用地图
Uri mapUri =Uri.parse("geo:100,100");
Intent intent =newIntent(Intent.ACTION_VIEW, mapUri);
// 播放mp3
Uri playUri =Uri.parse("file:///sdcard/test.mp3");
Intent intent =newIntent(Intent.ACTION_VIEW, playUri);
intent.setDataAndType(playUri,"audio/mp3");
// 调用拨打电话
Uri dialUri =Uri.parse("tel:10086");
Intent intent =newIntent(Intent.ACTION_DIAL, dialUri);
// 直接拨打电话,需要加上权限<uses-permission id="android.permission.CALL_PHONE" />
Uri callUri =Uri.parse("tel:10086");
Intent intent =newIntent(Intent.ACTION_CALL, callUri);
// 调用发邮件(这里要事先配置好的系统Email,否则是调不出发邮件界面的)
Uri emailUri =Uri.parse("mailto:zuolongsnail@163.com");
Intent intent =newIntent(Intent.ACTION_SENDTO, emailUri);
// 直接发邮件
Intent intent =newIntent(Intent.ACTION_SEND);
String[] tos ={"zuolongsnail@gmail.com"};
String[] ccs ={"zuolongsnail@163.com"};
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT,"the email text");
intent.putExtra(Intent.EXTRA_SUBJECT,"subject");
intent.setType("text/plain");
Intent.createChooser(intent,"Choose Email Client");
// 发短信
Intent intent =newIntent(Intent.ACTION_VIEW);
intent.putExtra("sms_body","the sms text");
intent.setType("vnd.android-dir/mms-sms");
<activity
android:name=".OtherActivity"
android:label="OtherActivity">
<intent-filter>
<action android:name="com.xiazdong.action"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.xiazdong.category"/>
<data
android:host="www.xiazdong.com"
android:scheme="xiazdong"/>
</intent-filter>
</activity>
Intent intent =newIntent();
intent.setAction("com.xiazdong.action");
intent.addCategory("com.xiazdong.category");
intent.setData(Uri.parse("xiazdong://www.xiazdong.com/xia"));
startActivity(intent);//此方法中调用intent.addCategory("android.intent.category.DEFAULT");
1.android开发中经常容易出现什么样的问题?有哪些技术难点?
2.屏幕适配方面是怎么做的?
3.版本适配是怎么做的?