0%

如果一味的new Thread,不用线程池,可能会导致同时执行很多线程,引发性能问题。比如在ListView里,每个item都有一张网络图片,如果在adapter里的getView方法里直接使用new Thread去异步下载图片,当划动listview时,如果速度快,就会产生几十甚至上百个下载线程。而使用线程池,就可以很方便管理线程。 代码来自Think in Java。 LiftOff.java:

package com.test;
public class LiftOff implements Runnable{
    protected int countDown=10;
    private static int taskCount=0;
    private final int id=taskCount++;
    
    public LiftOff() {
        System.out.println("#"+id+" created");
    }

    public LiftOff(int countDown)
    {
        this.countDown=countDown;
    }
    public String status()
    {
        return "#"+id+"("+(countDown>0?countDown:"Liftoff")+").";
    }
    @Override
    public void run()
    {
        while(countDown-->0)
        {
            System.out.println(status());
        }
        System.out.println("#"+id+" destory");
    }
}



package com.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //使用线程池管理线程,FixedThreadPool是一个限制线程数量的线程池,参数是线程数量
        //任何线程池,在有可能的情况下,现有线程会被利用
        ExecutorService exec=Executors.newFixedThreadPool(1);
        for(int i=0;i<2;i++)
        {
            exec.execute(new LiftOff());
        }
        exec.shutdown();
    }

}

看执行的结果: #0 created #1 created #0(9). #0(8). #0(7). #0(6). #0(5). #0(4). #0(3). #0(2). #0(1). #0(Liftoff). #0 destory #1(9). #1(8). #1(7). #1(6). #1(5). #1(4). #1(3). #1(2). #1(1). #1(Liftoff). #1 destory 可以看到,所有的LiftOff先构造完,然后再一个线程一个线程执行,因为我们限制了只能同时有一个线程。另外,SingleThreadExecutor就是线程数量为1的FixedThreadPool

打开~/.bash_profile(默认不存在该文件,创建),添加以下内容: export PATH=${PATH}:/Users/fhp/Documents/Applications/sdk/tools export PATH=${PATH}:/Users/fhp/Documents/Applications/sdk/platform-tools 重新打开终端,试试输入adb,奇怪的是不需要像Linux一样先用source载入配置文件。

FUI,是一个Flat UI的控件库,包含多个常用的Android控件,使用style/theme重写,如果您的项目当前没有自定义过控件,那么,换成FUI样式只需要修改AndroidManifest.xml中的一行代码。 设计源文件来自网络,下载地址:http://www.psdoc.org/ch/document/light_color_flat_ui_kit_input.html UI效果图: fui 包含控件: TextView,EditText,Spinner,ProgressBar,RadioButton,CheckBox,ToggleButton,Buttun,AutoCompleteTextView,HeadMenu,SearchBar. 其中:HeadMenu,SearchBar并非系统自带控件,如果要使用,需要多改几行代码。 项目已经开源,托管于OSChina,地址:http://git.oschina.net/pocketdigi/FUI 使用方法: 将FUI项目作为library引入你的项目中,修改您的项目的AndroidManifest.xml文件,在application标签中,添加 android:theme="@style/FTheme" 即可使项目中的标准Android控件变成Flat UI风格,具体可参考Demo.

与svn比较,git确实要复杂很多。建议新手朋友先看《Git Pro》这本电子书,用命令行操作一下,再来使用Eclipse的git插件,这样比较容易理解。 Git服务器以OSChina为例,创建帐号,新建项目就不介绍了。 我建了一个测试项目,地址是https://git.oschina.net/pocketdigi/test.git 很多文章都说第一步是给Eclipse装EGit插件,但我的Eclipse里已经自带了Git插件,也许版本不同的缘故,所以没有这一步。 以导入现有项目为例: 我这里的项目是AndroidTest. 第一步,配置本地仓库。 项目上点右键,选择小组-共享项目(英文版请自行翻译),在弹出的对话框里选择Git(如果没有,说明没装Git插件),下一步如下 git2 这一步是设置本地仓库的存放目录,我一般存在工作目录的子目录下,勾选Use or create repository in parent folder of project,再点击Create Repository按钮(前面勾了才会有),在项目根目录下创建.git目录用作本地仓库,再点完成。会发现包资源管理器里,AndroidTest项目图标已经改变, 第二步,提交代码到本地仓库。 在AndroidTest项目上点右键-小组-添加,将整个项目所有文件加入Git管理,然后项目上点右键-小组-落实,将代码提交到本地仓库。 第三步,配置远程仓库。 项目上点右键-小组-Remote-Push git4 把地址贴到URI处,再输入osc的用户名和密码,点下一步。 git5 在Source ref上点击下拉箭头,选择refs/heads/master,Destination ref会自动填充,点击Add Spec按钮,勾选Force Update,点完成,开始提交到远程服务器。 提交完后,刷新oschina网页,可以看到相关文件。 菜单栏上点窗口-显示视图-Git Repositories,打开Git Repositories视图。展开AndroidTest,再Remote上点右键,选择Create Remote git3 Remote name,随便输入一个名字,一般是origin,选择Configure push,确定,弹出下如 git6 点击更改,输入URI,OSC用户名密码,点完成,点击Ref mapping下的Edit(Advabced)…,弹出Push Ref Specifications对话框,点击Add All Branches Spec,不要勾选Force Update(勾了以后,即使服务器上有更新,也会提交成功),再点完成(如果之前没有先提交代码到服务器,这里过不去,因为服务器上没有任何分支)。点保存。设置成功后,如下图: git7,这里只是配置了Push,虽然自动添加了fetch,但我这个版本的git插件并没有配置fetch的Ref map,需要在包资源管理器上,项目上点右键,小组,Remote,Configure Fetch from upstream…配置Ref map 在Git Repositories视图中,在AndroidTest上点右键,选择Open Properties View(版本不同可能不一样,就是打开属性),会显示一个属性的视图,某些版本可能是对话框. git8 点击String Value右边的编辑按钮,弹出属性编辑对话框。 git9 点击New Entry按钮,添加两条属性: Key = branch.master.remote Value = origin Key = branch.master.merge Value = refs/heads/master 配置完成。 当在本地修改过代码后,需要提交到服务器,如果服务器上的相关代码已经被修改(别人提交过),需要先从服务器pull下最新的代码,解决冲突,才能提交。 获取远程服务器代码:小组(项目上右键点击操作省略不写,下同)-Pull 代码提交到本地仓库:小组-落实 标记冲突已经解决后:小组-添加(之前介绍git命令的文章说过,git add不同的情况功能不同) 提交到远程服务器:小组-Push to upstream 基本流程应该是:改代码,pull,解决冲突,标记冲突已经解决,commit(提交到本地仓库),push(提交到远程仓库)

这个不是git教程,不解释其中专业术语. git init 从当前目录初始化 git clone url 从远程克隆项目 git status 查看文件状态 git add file 根据文件不同的状态,有不同的功能,如果文件是Untracked,就是track文件,如果文件not staged,则是把文件放入stage.参数-A 表示添加所有文件 git commit 提交staged的文件,加-m加上这次提交的说明,不加会要求输入说明.加-a可以跳过git add到stage的步骤.加上–amend,重新提交(撤销上次提交,重新提交) git diff 查看工作目录中与staged文件的修改之处,加上–staged,查看staged文件和之前已提交的仓库里的文件修改之处. git rm file删除stage里的指定文件,同时删除工作目录里的文件.再次commit后,该文件就不会纳入管理.如果要取消tracked(删除仓库和stage里信息),且不删除工作目录文件,加上–cached,目录加上-r递归 git mv file 移动文件,相当于执行mv from to,git rm from,git add to三条命令 git log 查看提交的日志 -p展开每次提交内容差异 -5显示最近5次更新,–stat 只显示增改行数统计 git checkout – file 从仓库中取出指定文件,覆盖工作目录中的对应文件 git remote add name url 添加远程仓库URL,name为别名 git remote rename name1 name2 把远程仓库别名为name1改成name2 git remote -v 显示远程仓库列表 git remote rm name 删除已经添加的远程仓库 git fetch name 从别名为name的远程URL获取本地仓库没有的数据 git pull name branch 从别名为name的远程仓库拉取分支branch,合并到本地工作目录. git push name branch 将本地仓库推送到远程服务器指定分支(需要先pull远程最新内容) git remote show name 显示指定远程仓库信息 git reset HEAD file… 撤销暂存的文件 git update-index –assume-unchanged file 不再track指定文件 git update-index –no-assume-unchanged file 继续track指定文件 标签: git tag -a tagname -m ‘comment’ 打标签 git push origin tagname 推送标签到服务器 git tag -d tagname 删除本地标签 git push origin :refs/tags/tagname 推送删除远程标签 pull时冲突: git stash git pull git stash pop 会自动merge,再做处理 git clean -fd 清除所有未跟踪的文件 分支操作: git branch 列出分支,加-v会列出最后一次提交,加-a列出远程分支 git branch 1.2 创建分支名为1.2的分支 git checkout 1.2 切换当前工作分支到1.2 git checkout -b 1.2 checkout加上b参数,会自动创建分支并切换,一条顶上面两条 git branch -d 1.2 删除1.2分支 git merge 1.2 把1.2分支合并到当前工作的分支。git会自己决定当前分支还是1.2作基础 git branch –merged 筛选出你已经与当前分支合并的分支,注:创建分支时会以当前分支为基础创建,所以当前分支已经合并到新分支里 git branch –no-merged 筛选出与当前分支未合并的分支 git branch -D 1.2 强制删除未合并的分支(-d会报错,不让删) git push 远程仓库名 分支名 推送本地分支到远程仓库,git remote -v查看远程仓库 git push origin :分支名 删除远程分支,注意origin后有空格

extends关键字用于指定泛型类继承自哪个类或实现哪些接口,在使用的时候就可以调用父类和接口里的public方法 如:

    public  & IFactory2> Foo(F factory)
    {
        x=factory.create();
    }

其中FF是父类,IFactory和 IFactory2是接口,中间用&隔开,如果有父类,父类必须放在第一个,后面才可接上接口。 传入参数factory,必须继承自FF类,并且实现IFactory和 IFactory2接口.

使用泛型的类中,要实例化一个泛型类的对象时,不能使用new,可以使用class.newInstance(),但是该类刚好没有默认无参的构造方法,也会出错。所以最好的方法是用工厂模式。 IFactory.java:

/**
 * 工厂接口,包含create方法
 * @author fhp
 *
 * @param 
 */
public interface IFactory {
    T create();
}

Foo.java:

/**
 * 成员带有泛型的类
 * @author fhp
 *
 * @param 
 */
public class Foo {
    private T x;
    //构造方法传入一个实现IFactory的工厂
    public > Foo(F factory)
    {
        x=factory.create();
    }
    public T get()
    {
        return x;
    }
}

StringFactory.java:

/**
 * 工厂实现类
 * @author fhp
 *
 */
public class StringFactory implements IFactory {
    @Override
    public String create() {
        // TODO Auto-generated method stub
        return "String Factory";
    }
}

使用:

        Foo foo=new Foo(new StringFactory());
        System.out.println(foo.get());

一般情况下,我们使用泛型是这样的:

Map map2=new HashMap();

前后都需要加上参数的类型,编译器无法从等号前的参数类型自动推测出后面的参数类型,但使用泛型类型参数推断可以简化部分工作。

    /**
     * 定义泛型方法
     * @return
     */
    public  Map map()
    {
        return new HashMap();
    }
    
    public void ff()
    {
        //调用时,会自动根据前面的参数类型返回所需的map
        Map map=map();
        Map map2=map();
    }

但是,不能直接将map()方法作为其他方法的参数传入,因为它没法判断所需的类型。需要显示说明:

    public void ff(Map m)
    {
    }
        //调用
        Main main=new Main();
        main.ff(main.map());

一个方法,只能有一个返回值,如果我们要返回多个对象,不用元组的话,唯一的方法就是建一个类,包含这些对象,然后返回这个类的实例,但这么一来,每个方法,如果返回的对象不同,就得定义一个不同的类。元组,就是定义一个类,包含有指定数目,但不定类型的对象,配合泛型,对象可以是任意类型。

/**
 * 容纳两个对象
 * @param 
 * @param 
 */
public class TwoTuple {
    //定义成final,返回后不可修改
    public final A first;
    public final B second;
    public TwoTuple(A a,B b)
    {
        first=a;
        second=b;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return first.toString()+second.toString();
    }
}
/**
 * 
 * 容纳三个对象
 *
 * @param 
 * @param 
 * @param 
 */
class ThreeTuple extends TwoTuple{
    public final C third;
    public ThreeTuple(A a,B b,C c)
    {
        super(a, b);
        third=c;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return super.toString()+third.toString();
    }
}

****使用方法:

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TwoTuple two=f();
        System.out.println(two);
        System.out.println(two.first);
        System.out.println(two.second);
        
    }
    public static TwoTuple f()
    {
        TwoTuple two=new TwoTuple("asfdsaf", 55535);
        return two;
    }****

代理可以将额外的操作和实际对象分离,类似于一个中间人的角色,使用基类或接口作为参数,这样在需求有变动时就很容易修改,也可以在代理中监控各个方法的调用。 以下代码摘自《Think in Java》 接口Interface.java:

public interface Interface {
    void doSomething();
    void somethingElse(String arg);
}

实现 RealObject.java:

public class RealObject implements Interface {

    @Override
    public void doSomething() {
        // TODO Auto-generated method stub
        System.out.println("doSomething");
    }

    @Override
    public void somethingElse(String arg) {
        // TODO Auto-generated method stub
        System.out.println("somethingElse"+arg);
        
    }

}

SimpleProxy.java:

/**
 * 简单的代理模式,把对象隐藏起来,通过自身暴露的方法来调用
 *
 */
public class SimpleProxy {
    private Interface proxied;
    public SimpleProxy(Interface proxied)
    {
        this.proxied=proxied;
    }
    public void doSomething() {
        System.out.println("SimpleProxy doSomething");
        proxied.doSomething();
    }

    public void somethingElse(String arg) {
        System.out.println("SimpleProxy SomethingElse"+arg);
        proxied.somethingElse(arg);
    }
}

动态代理操作,支持任意对象方法的调用 DynamicProxyHandler.java:

public class DynamicProxyHandler implements InvocationHandler {
    private Object proxied;
    public DynamicProxyHandler(Object proxied)
    {
        this.proxied=proxied;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        if(args!=null)
        {
            for(Object arg:args)
            {
                System.out.println(" arg"+arg);
            }
        }
        return method.invoke(proxied, args);
    }
}

使用方法 SimpleDynamicProxy.java:

public class SimpleDynamicProxy {
    public static void main(String[] args)
    {
        //代理
        RealObject real=new RealObject();
        SimpleProxy simpleProxy=new SimpleProxy(real);
        simpleProxy.doSomething();
        simpleProxy.somethingElse("bonobo");
        //动态代理
        Interface proxy=(Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(),new Class[]{Interface.class}, new DynamicProxyHandler(real));
        proxy.doSomething();
        proxy.somethingElse("bonobo");
    }
}