分类目录归档:android资料

Android中的进程与多线程的讲解(Handler和AsyncTask)

    Hello EveryBody,又到了我们相聚的时间了,今天要总结的东西现在有点迫不及待了,因为在实际的应用中如果用不到它,我们就不能再听歌的同时发送信息,其实大家应该都知道了,今天的主角就是进程与多线程,好了,其他的不多说,直接进入正题吧。

一.Android进程的分类:

(1)前台进程:即与用户正在交互的Activity或者Activity用到的Service等,如果系统内存不足时前台进程是最后被杀死的;

(2)可见进程:可以是处于暂停状态(onPause)的Activity或者绑定在其上的Service,即被用户可见,但由于失去了焦点而不能与用户交互;

(3)服务进程:其中运行着使用startService方法启动的Service,虽然不被用户可见,但是却是用户关系的,例如用户正在非音乐界面听的音乐或者正在非下载页面自己下载的文件等;当系统要用空间运行前两者进程时才会被终止;

(4)后台进程:其中运行着执行onStop方法而停止的程序,但是却不是用户当前关心的,例如后台挂着的QQ,这样的进程系统一旦没有内存就首先被杀死;

(5)空进程:不包含任何应用程序的程序组件的进程,这样的进程系统是一般不会让他存在的;

二.进程与多线程的深入

1.由于单线程而导致的ANR错误:

ANR错误(Application Not Responding),指主UI进程被阻塞超过5秒钟而出现的错误,它会终止程序的正常运行,我们要避免它 ,而产生ANR错误的原因就是:单线程。

例子如下:

package com.example.l0902_anr;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {@Override
public void onClick(View v) {
int count=0;
while(count<1000){
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});}
}

运行效果如下:

OK,上面的程序出问题的原因是单线程,那么我们可以再创建一个线程去处理耗时操作,就不会阻碍主UI的操作了:

改动上面的程序如下:

package com.example.l0902_anr;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btn,btn_stop;
private Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button) findViewById(R.id.btn);
btn_stop=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
thread=new Thread(new Runnable() {
@Override
public void run() {
int count=0;
while(count<1000){
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
}
}
});
thread.start();//启动线程
}
});
btn_stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
thread.stop();//停止线程
}
});
}
}

运行效果如下:

代码写到这里,ANR错误就解决了,但是又出现一个新的问题,如果我想把利用新的线程来更新主UI线程,可以不可以呢,好吧,我们用上面的程序试一试,加一个TextView来接收新的线程中自增的数据,看看是否能实现:

程序修改如下:

package com.example.l0902_anr;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button) findViewById(R.id.btn);
tv=(TextView) findViewById(R.id.tv);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
int count=0;
while(count<1000){
count++;
tv.setText(count+"");//试图更新主UI线程
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();//启动线程
}
});
}
}

运行效果如下:

我们可以看到程序被意外终止了,那么说明其他线程是不能更改主UI的数据的,除非...除非我们往下看...

2.Android线程之间的通信——Handler

其实,Android线程之间的通信不只是Handler,还需要Message,MessageQueue,Looper的相互使用,Android线程通信模型如下:

(1)Message:即要传递的消息;

(2)MessageQueue:存放消息的队列;

(3)Looper:用于创建MessageQueue以及循环使用其中的Message;

(4)Handler:用于消息的传递了;

好了,我们直接看下面的例子吧:

package com.example.l0902_handler;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn_start,btn_stop;
private TextView tv;
private int i=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_start=(Button) findViewById(R.id.button1);
btn_stop=(Button) findViewById(R.id.button2);
tv=(TextView) findViewById(R.id.textView1);
btn_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//开始发送消息
handler.post(runnabl);
}
});
btn_stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//停止发送消息
handler.removeCallbacks(runnabl);
}
});
}
//创建新的线程
private Runnable runnabl=new Runnable() {
@Override
public void run() {
i++;
//使用Message封装非UI线程的消息
Message m=new Message();
//使用Message的arg1属性或者arg2属性传递int类型的消息效率高
m.arg1=i;
//使用Handler发送消息
handler.sendMessage(m);
}
};
@SuppressLint("HandlerLeak")
private Handler handler=new Handler(){
public void handleMessage(Message m){
System.out.println(m.arg1);
String str=m.arg1+"";
//注意:一定一定要记得TextView是String类型哦
tv.setText(str);
handler.post(runnabl);
}
};
}

运行结果如下:

看到了吧,主UI的数据是不是更新了呢,很是神奇吧,这就是线程之间的通信了。

接下来我们要继续讲一个线程通信的机制。。。

3.简化多线程通信开发的——AsyncTask

我们直接用例子说明AsyncTask的使用吧:

(1)我们同样也先写一个类似上面的ANR错误的卡屏的例子:

package com.example.l0902_myasynctask;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btn1,btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1=(Button) findViewById(R.id.button1);
btn2=(Button) findViewById(R.id.button2);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
//超过5秒了,其实就和前面的例子一样了(ANR错误)
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("Hello To EveryOne");
}
});
}
}

运行效果如下:
如果把上面等待的时间改为5以内,则就是典型的卡屏的例子了,试试看吧:初始界面:

点击下面的按钮:

点击上面的按钮:此时就卡住了,屏幕什么都干不了了

卡屏期间点击了多少下下边的按钮,5秒之后都会显示出来:

上面就是经典的卡屏的例子,怎么解决呢?当然是:AsyncTask了

(2)使用AsyncTask创建后台进程,解决卡屏问题:

代码如下:

MainActivity.java

package com.example.l0902_myasynctask;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btn1,btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1=(Button) findViewById(R.id.button1);
btn2=(Button) findViewById(R.id.button2);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//创建AsyncTask并执行
new MyAsyncTask().execute();
}
});
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("Hello To EveryOne");
}
});
}
}MyAsyncTask.java:package com.example.l0902_myasynctask;
import android.os.AsyncTask;
/**
* 在后台创建线程,不会出现卡屏现象
* @author asus
*/
public class MyAsyncTask extends AsyncTask<Void, Void, String>{
//核心方法,在后台启动一个线程
@Override
protected String doInVoid...  params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}运行效果我们就不再给出了,描述一下就可以了,即无论我们是否按卡屏按钮,执行按钮都能正常输出,这正是因为AsyncTask创建了一个后台进程来处理耗时功能,不影响主UI的正常功能的处理。

(3)最后总结一个使用AsyncTask的例子——下载滚动条的进度:

MainActivity.java:

package com.example.l0902_usinganysc;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
private ProgressBar bar;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button) findViewById(R.id.button1);
bar=(ProgressBar) findViewById(R.id.progressBar1);
tv=(TextView) findViewById(R.id.textView1);
tv.setText("开始下载");
btn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
MyAsyncTask my=new MyAsyncTask(tv, bar);
my.execute("","i=","打开文件");//启动方法
}
});
}
}

MyAsyncTask.java:

package com.example.l0902_usinganysc;
import android.os.AsyncTask;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* 总结:参数相关
* @author asus
*/
public class MyAsyncTask extends AsyncTask<String, Integer, String>{
private ProgressBar bar;
private TextView tv;
//构造方法,初始化ProgressBar和TextView
public MyAsyncTask(TextView tv,ProgressBar bar){
this.bar=bar;
this.tv=tv;
}
/*
* 这个方法的参数不能改,其返回类型与第三个参数一致,其参数与第一个参数类型一致
* (non-Javadoc)
* @see android.os.AsyncTask#doInParams[])
*/
@Override
protected String doInString...  params) {//可变参数
String p1=params[1];
String p2=params[2];
int i=1;
for(i=1;i<=100;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return p1+i+p2;//也作为下一个方法的参数
}
/*
* 当异步结束时触发此方法,其参数类型与第三个参数类型一致
* (non-Javadoc)
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(String result) {
if(result!=null){
tv.setText("下载完成"/*+result*/);
}
super.onPostExecute(result);
}
/*
* 当异步开始的时候触发
* (non-Javadoc)
* @see android.os.AsyncTask#onPreExecute()
*/
@Override
protected void onPreExecute() {
System.out.println("异步开始");
tv.setText("开始下载");
super.onPreExecute();
}
/*
* 正在处理的时候触发,与主UI线程交互,其参数与第二个参数一致
* (non-Javadoc)
* @see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
@Override
protected void onProgressUpdate(Integer... values) {//第二个可变参数,由上面的publishProgress方法的参数决定
bar.setProgress(values[0]);
tv.setText(values[0]+"%");//可变参数就是这么用的,values[1]表示publishProgress的第二个参数
super.onProgressUpdate(values);
}
}

运行效果如下:

好了。今天的内容就到这里了,希望真的能帮到你,如果有需要改进的地方请多多指出批评和指点,我欣然接受哦O(∩_∩)O哈哈~

本文出自 “MySpace” 博客,请务必保留此出处http://wangzhaoli.blog.51cto.com/7607113/1287545

Material Design的一次设计探索

原文出处: Arthur Bodolec 译文出处:阿里UED - 郭楠

【译者注】作为一个移动界面设计师,如果你已经细细读过Material Design的设计指引,那么这篇文章是一篇很好的设计案例。如果你还没有读过,那这篇文章一定是个最容易最生动的起点,以小窥大得帮助你进入Material Design的世界。 大家知道,google最近发布了Android的Lollipop系统,系统的一个重大改动是引入了一种新的视觉语言:Material Design。随着新系统的发布,安卓也发布了一个跨平台的视觉、动效、交互设计的全面指引。10月7日,Google的Material Design体验团队组织了一个workshop,跟第三方app团队分享了一些设计见解和小技巧,来指导他们在Android平台的设计。

在我看来,Android的这次改进,是在对的方向上又迈进了实实在在的一步。这个新系统目前已经拥有足够的一致性和灵活性,足以兼容任何新app 的设计。所以呢,我在回来之后也重新回到我feedly的设计稿,尝试将feedly的界面根据Material Design的设计指引,做一次重新设计的尝试。

这次尝试,我的主要目的是创造一个完全根据Google的Material Design原则优化的全新版本。这个版本可以指引设计团队的未来设计。同时,我们还可以选用其中的一些设计点,立即落地并发布在以后的版本中。这次尝试 的第二个目的,是为feedly获得一些用户反馈。所以如果你有任何建议,请留下些评论。

这篇文章里,不仅有这次重新设计的结果,也讲述了过程中的设计思考。

好了,进入正题,让我们马上开始Material Design的探索。 总览 在这次重新设计中,我着重设计feedly的几个主要界面。下图是设计前(上排)和设计后(下排)的对比图。 Material Design的设计指引要是全面描述的话,会太繁杂。所以在这里我提取出四个核心设计要点,这四个核心要点也是我用来重新设计的主要依据。 一、有形的界面(Tangible Interfaces) Material Design 设计原则

“在material design中,app里的每个像素都被呈现在一张纸(a sheet of paper)上。这张纸有单一的背景颜色,并且根据不同的环境可以被随意缩放。一个典型的界面排版,可能由好几张不同大小的纸张的重叠构成。”

设计原则在feedly的运用 Feedly原有的界面已经在运用类似的纸张隐喻,我们的主要设计元素是一叠叠的卡片,每个卡片上都有文章列表或文章。上滑卡片,下一张卡片就会被显示出来。这种隐喻正好和Material Design可以完美契合。

Feedly的导航位于左侧的面板上,面板可以被滑出,盖在那叠卡片上。Feedly的“发现”界面也是同样逻辑,只是位于右侧。 二、让设计更像印刷品 Material Design 设计原则

“印刷品设计的基本元素包括字体排印、网格、间隙、尺寸、颜色和图像的运用方式。这些元素的意义远不仅仅是好看而已,他们一起能创造层次、制造意义及带来视觉焦点。”

设计原则在feedly的运用 8点网格 Google提供了一些很好的资源,来帮助设计师在设计app的时候,能以一种保有一致性的方式来缩放和安排视觉元素。但是你仍然需要了解这背后的 总体网格系统。虽然这是一个8点的网格系统,Android常常将边距设置为16点。除了在各个界面贯彻网格系统,我还将我们的杂志视图页面边距设置成了 16点(2×8)宽,将缩略图设置为96点(12×8)宽。 颜色和图像 Google推荐在工具栏和状态栏使用app的主色(主色一般是品牌的主色调)。但因为feedly是一个阅读应用,如果在这些区域运用我们的亮绿色,会对视线造成强烈的干扰,打扰用户对实际内容的阅读。因此,我选择在这些区域运用浅灰色,减少对内容的打扰。

在左边栏中,我设计了一个运用亮绿主色的顶栏,顶栏用来突出显示当日的热点话题。这种方式即强调了关键信息,又变现了品牌色,我对这种方式还比较满意。

图像也是设计中非常重要的元素。在杂志视图中,我用了全出血尺寸的图像来呈现需要深度阅读的文章。在发现界面中选中某话题时,也运用了全出血的图片作为界面头部。 三、有意义的转场 Material Design 设计原则

“有时候,用户会搞不清楚需要关注界面的哪部分,或在一个元素从A位置变换到B位置的时候感到迷惑。通过经过精心编排的动 效设计,可以在app使用过程中有效地引导用户的注意力和视觉焦点,避免当布局变化或元素重新排布时引起的迷惑,同时提升整体的体验美感。动效设计应该满 足功能性的目标,不仅仅是炫技。”

设计原则在feedly的运用 打开文章和关闭文章,是feedly中最重要的转场。在这个过程中,用户在文章的列表和整篇文章内容中切换。制作这个转场动效时,我参考了Material Design设计原则中推荐的3个主要设计指引。 表面的反馈 当用户点击文章预览时,我运用了点击波纹效果来提供即时反馈。波纹效果会扩大充满整个文章预览元素。同样,当用户关闭文章时,点击波纹效果也会在顶栏中出现。 视觉连续 在杂志视图中的预览图片,会在界面转换到文章视图的过程中放大,并移动到相应的位置。通过这样的转场,用户能完美感知到他所点击的元素和最终界面元 素之间的关系。但这其中有一个挑战:有时在预览视图中的图片并不出现在文章的首屏,而是好几屏之后才会看到。这时,我们不得不在转场时将文章内容渐显,而 将缩略图渐隐来过渡。 有形的表面 这很可能是Material Design中最重要的要素。根据设计指引,我们需要将内容处理为像打印在有形表面上一般。当用户点击了列表中的文章预览区域时,这个模块会向上升起,创 造出属于这篇文章的一个新的平面。同时考虑到视觉的连续,这个新平面会放大,使其成为界面中最主要的一个面。在这个过程中,文章的内容也渐显出现。

综合这些设计指引,我们得到的最终动效是: 四、自适应设计 Material Design 设计原则

“Material Design的最后一个核心理念,是创造出一个自适应的设计,他能适用在从小手表到大电视的任何尺寸的平台上。一个自适应的设计,实际上是在同一个底层结 构的体系中,演变出适应于不同尺寸界面的设计。在每一种设计中,尺寸和交互方式用最适合这个尺寸界面的方式展现;但在颜色、图标语言、层级和空间关系上却 保持不变。Material Design通过提供灵活的元素和样式,帮助你搭建可自适应的界面。”

设计原则在feedly的运用 从第一版开始,feedly就已经是一个可自适应的应用。自适应时,最主要需要考虑的元素就是用来呈现文章的卡片。考虑如何将这些卡片排布在杂志视图中,是一件很有意思也很有挑战的事情。正如你在下图看到的,不同尺寸的屏幕采用了不同的、但都很有趣的布局。 最后,希望你在跟随我进行Material Design探索的时候能乐在其中。如果你有任何的反馈或想法,能让feedly更好地兼容这些设计原则,请不要犹豫留下你的评论。

Android杂谈–LayoutInflater和MenuInflater用法

来源:http://www.cnblogs.com/loulijun/archive/2011/12/28/2305452.html

前言

LayoutInflater用法

LayoutInflater是一个用来实例化XML布局为View对象

应用程序运行时会预先加载资源中的布局文件,如果layout布局中的资源比较多,会影响性能,所以可以选择LayoutInflater方式用的时候加载,这样减轻了应用程序运行时很多负担

public View inflate (int resource, ViewGroup root)

从指定的XML资源中填充一个新的视图

参数resource:将要加载的XML布局id,例如R.layout.list_item

参数root:父视图,可选项,一般为Null

public static LayoutInflater from (Context context)

从给定的context获取LayoutInflater

可以通过如下三种方式获取LayoutInflater

第一种:

        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View myView = inflater.inflate(R.layout.main, null);

第二种:与第一种方法相同,即from方法封装了getSystemService(...)等

        LayoutInflater inflater = LayoutInflater.from(context);
        View myView = inflater.inflate(R.layout.main, null);

第三种:getLayoutInflater()方法是Activity的方法,归根到底还是第一种方式

        LayoutInflater inflater = getLayoutInflater();
        View myView = inflater.inflate(R.layout.main, null);

所以我们在加载布局的时候可以用setContentView直接设置,然后通过findViewById()来获取控件的id
例如:我们可以用4种方式加载main.xml布局文件,不过LayoutInflater一般多用于ListView等地方,

如BaseAdapter的getView()方法会用到:http://www.cnblogs.com/loulijun/archive/2011/12/28/2305016.html

package com.loulijun.demo6;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class Demo6Activity extends Activity {
    private Button btn;
    private TextView tv;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //----------第一种方式----------
//        setContentView(R.layout.main);
//        btn = (Button)findViewById(R.id.btn);
//        tv = (TextView)findViewById(R.id.tv);
        //----------第二种方式----------
//        LayoutInflater inflater = getLayoutInflater();
        //----------第三种方式----------
//        LayoutInflater inflater = LayoutInflater.from(this);
        //----------第四种方式----------
        LayoutInflater inflater = (LayoutInflater)this.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.main, null);
        setContentView(view);
        btn = (Button)view.findViewById(R.id.btn);
        tv = (TextView)view.findViewById(R.id.tv);
       btn.setOnClickListener(new Button.OnClickListener()
       {

        @Override
        public void onClick(View v) {
            //...
        }
           
       });
    }

使用setContentView(R.layout.main)设置布局后布局会立刻显示,而使用inflate()方法加载的布局文件 得到的是一个View视图对象,在需要的时候再setContentView(view)即可。在Activity中一般只需要 setContentView即可,如果是非Acitivity,则需要使用LayoutInflater来动态加载控制控件

MenuInflater用法

MenuInflater是用来加载menu布局文件的,与上面的类似

与LayoutInflater类似,应用程序运行时会预先加载资源中的布局文件,如果Menu布局中的资源比较多,会影响性能,所以可以选择MenuInflater方式用的时候加载,这样减轻了应用程序运行时很多负担

与LayoutInflater相比,MenuInflater用法要简单很多,它只有Activity.getMenuInflater()方法。

例如:

1、在res目录下创建menu文件夹,在里面创建mymenu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:title="打电话"
        android:icon="@android:drawable/ic_menu_call"
        android:id="@+id/action_call"/>
  <item 
        android:title="照相"
        android:icon="@android:drawable/ic_menu_camera"
        android:id="@+id/action_camera"/>
  <item
        android:title="添加"
        android:icon="@android:drawable/ic_menu_add"
        android:id="@+id/action_add"/>
  <item 
        android:title="删除"
        android:icon="@android:drawable/ic_menu_delete"
        android:id="@+id/action_delete"/>
</menu>

2、重写onCreateOptionsMenu方法和onOptionsItemSelected方法之后,在onCreateOptionsMenu中使用MenuInflater加载布局

package com.loulijun.demo6;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;

public class Demo6Activity extends Activity {
    private Button btn;
    private TextView tv;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        //填充菜单
        inflater.inflate(R.menu.mymenu, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId())
        {
        case R.id.action_add:
            //操作
            break;
        case R.id.action_call:
            break;
        case R.id.action_camera:
            break;
        case R.id.action_delete:
            break;
        }
        return super.onOptionsItemSelected(item);
    }
    
}

android的ADT-Bundle环境快速创建

正文:

ADT-Bundle for Windows 是由Google Android官方提供的集成式IDE,已经包含了Eclipse,你无需再去下载Eclipse,并且里面已集成了插件,它解决了大部分新手通过eclipse来配置Android开发环境的复杂问题。

有了ADT-Bundle,新涉足安卓开发的同学也无需再像以前那样在网上参考繁琐的配置教程,可以轻松一步到位进行Android应用开发。

第一步:JAVA SDK(JDK)的安装:

可以去问百度下载JDK,也可以到官方下载JDK。

官方下载地址: http://www.oracle.com/technetwork/java/javase/downloads/index.html

这个更快捷: http://pan.baidu.com/s/1qWpw4EC

 

第二步: 下载ADT-Bundle for Windows

官方下载地址:http://developer.android.com/sdk/index.html 这个地址非常慢, 建议考虑下面的地址

http://tools.android-studio.org/ 这个里面有非常多的 重要的android资源下载

如果您要 安装windows版本, 可以直接使用如下地址

http://pan.baidu.com/s/1nt0XUI1

 

第三步:安装ADT-Bundle

直接把下载下来的的adt-bundle-windows-xxx-xxx.zip,解压到你需要安装的位置。

 

第四步:安装Android SDK

打开解压出来的文件夹里面的 SDK Manager.exe (也可以运行eclipse/eclipse.exe 然后通过Windows -> Android SDK Manager打开) 这个方法打开的 下载功能速度非常慢, 参考文章最后的 解决办法, 已经测试,完全可以解决。

勾选上你想要开发的目标手机安卓版本,最好是全部勾上,然后点击Install Package 按提示 next,accept允许等待安装(这是一个慢长的过程)

第五步:配置Android AVD(虚拟模拟器)

打开Eclipse(eclipse/eclipse.exe),(运行启动的eclipse可能看上去有些不一样,可以通过windows把一些常用的窗口,工具条显示出来),然后从Windows->Android Virtual Device Manger打开AVD管理器。

点击 New按钮 创建你一新的AVD,如下图,我做了一个简单说明,参数其实你都是可以自己随意填的,点击OK就行了。

你配置的这个AVD是会做为你安卓应用的默认调试摸拟器,当然你也可以配置多个。

 

第六步:创建一个Hello World项目

通过File -> New-> Android Application Project, 然后输入Hello World(项目名字),next,finish。

 

第七步:从运行Hello World

直接点击Run Debug(快捷键F11)就可以在你配置的模拟器里运行了。

 

有了ADT-Bundle这个东西,方便了很多。

 

Android SDK Manager国内下载缓慢的问题

①在Android SDK Manager Setting 窗口设置HTTP Proxy server和HTTP Proxy Port这个2个参数,分别设置为:

 

HTTP Proxy server:mirrors.neusoft.edu.cn

HTTP Proxy Por:80

如下图:

android-sdk-down

②options>Force ..http://...sources to be fetched using http://..选中该选项

③Packages>reload 即可

附一张效果图

Android官方图片加载利器BitmapFun解析

来源:http://www.cnblogs.com/purediy/p/3462822.html

通过BitmapFun在项目中使用,结合代码了解一下BitmapFun加载图片的原理,以及最佳使用实践。本文说明不包括BitmapFun的缓存部分。

Android开发在使用ListView和 GridView时,可能会有很多网络图片需要加载,通常我们会为每个图片加载启动一个Thread或者直接使用官方提供的AsyncTask,来做 Http异步加载,但当每个ImageView子视图都触发一个AsyncTask来异步加载图片时,这样就会产生如下问题:

1. 当用户快速滑动时,ImageView已经被回收,而绑定的线程还在运行,浪费CPU,浪费内存。

2. 无法确保当前视图在结束时,分配的视图已经进入循环队列中给另外一个子视图进行重用,意思就是,图片显示错位了,不该显示到当前问题的图片却显示了,这个 是经常遇到的问题。可以结合Adapter中的getView方法的convertView参数理解,ListView是回收和重复利用item的。

3. 无法确保所有的异步任务能够按顺序执行。

在这些问题下,官网给出的答案是,使用下面的方法来保证:

1. ImageView和Task绑定准确的加载对应图片;

2. ImageView和Task无法对应时则取消任务;

BitmapFun实现多线程并发加载图片的原理:

一个类,两个方法:

class AsyncDrawable extends BitmapDrawable{...}

boolean cancelPotentialWork(String url, ImageView imageView){...}

ImageViewResizeTask getBitmapWorkerTask(ImageView imageView){...}

具体代码实现如下:

/**
* 扩展BitmapDrawable类,通过弱引用关联任务BitmapWorkerTask
* BitmapDrawable被用来作为占位图片,绑定任务到ImageView中
*/
private class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> viewResizeTaskReference;

public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask viewResizeTask) {
super(res, bitmap);
viewResizeTaskReference = new WeakReference<BitmapWorkerTask>(viewResizeTask);
}

public BitmapWorkerTask getBitmapWorkerTask() {
return viewResizeTaskReference.get();
}
}

/**
* 确保ImageView执行的是它对应的Task,否则取消任务
* @param url
* @param imageView
* @return
*/
private boolean cancelPotentialWork(String url, ImageView imageView) {
// 获得ImageView对应的Task
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

if (bitmapWorkerTask != null) {
final String imgUrl = bitmapWorkerTask.url;
if (imgUrl == null || !imgUrl.equals(url)) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}

/**
* 获得已经被分配到ImageView的指定的Task
* @param imageView
* @return
*/
private BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}

使用方法:

/**
* 异步加载图片
* @param url
* @param imageView
*/
private void loadBitmap(String url, ImageView imageView) {
if (cancelPotentialWork(url, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
final AsyncDrawable asyncDrawable = new AsyncDrawable(context.getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(url);
}
}

/*
* 异步加载图片Task类
*/
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
...

@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}

if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}

最佳使用实践,提高流畅度

1. 设置ListView的OnScrollListener事件,在滑动的时候不加载图片

public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
if (!Utils.hasHoneycomb()) {
mImageFetcher.setPauseWork(true);
}
} else {
mImageFetcher.setPauseWork(false);
}
}

2. 在Activity或Fragment的onResume(),onPause(),onDestroy()方法中调用恰当方法非常有用

@Override
public void onResume() {
super.onResume();
mImageFetcher.setExitTasksEarly(false);
}

@Override
public void onPause() {
super.onPause();
mImageFetcher.setPauseWork(false);
mImageFetcher.setExitTasksEarly(true);
mImageFetcher.flushCache();
}

@Override
public void onDestroy() {
super.onDestroy();
mImageFetcher.closeCache();
}