整理的7款常用的开源免费的Android UI组件及官方下载地址

 更新时间:2016年9月20日 19:58  点击:2490
Android开发技术日趋成熟,开源社区也涌现了很多开源UI项目,以下是笔者整理的7款Android开发者常用的Android UI组件及官方下载地址。

Android开发是目前最热门的移动开发技术之一,随着开发者的不断努力和Android社区的进步,Android开发技术已经日趋成熟,当然,在Android开源社区中也涌现了很多不错的开源UI项目,它们可以帮助Android开发者更方便快捷地完成想要的功能。本文是Android系列的第一篇,主要是向大家推荐一些常用的Android UI组件,它们都是开源的。

1、图表引擎 - AChartEngine

AChartEngine是一款基于Android的图表绘制引擎,它为Android开发者提供了很多实用的图表绘制工具类,如果你需要在Android应用中添加可视化统计的功能,那么AChartEngine是一个不错的选择。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

官方网站:https://code.google.com/p/achartengine/

2、图表引擎 - MPAndroidChart

MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,应用起来非常灵活。和前面介绍的AChartEngine相比,MPAndroidChart显得更为轻巧和简单,MPAndroidChart同样拥有常用的图表类型:线型图、饼图、柱状图和散点图。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

官方网站:https://github.com/PhilJay/MPAndroidChart

3、地图引擎 - OSMDroid

OSMDroid是一款基于Android的模块化地图引擎,如果你觉得Android内置的MapView 类不能满足项目的要求,那么可以试试OSMDroid。它是完全模块化的,可以让你的Android应用程序更加灵活可控。OSMDroid支持在线和离线地图以及覆盖地图,支持标注图标、位置跟踪和绘制形状等功能,因此你可以完全定制地图的展示方式和地图数据的存取。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

官方网站:https://code.google.com/p/osmdroid/

4、日历日期组件 - Mobi Pick

Mobi Pick是一款Android风格的日期选择组件,主要利用了jQuery Mobile脚本库。Mobi Pick提供了3种不同的日期选择功能,最简单的日期选择功能是选择年月日,另外一种是可以自定义修改年月日,还有一种是可以下拉选择日期。由于Mobi Pick有着Android的风格样式,因此外观相当漂亮。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

官方网站:http://mobipick.sustainablepace.net/

5、滚动组件 - Glide

Glide是一款基于Android的图片加载和图片缓存组件,它可以最大性能地在Android设备上读取、解码、显示图片和视频。Glide可以将远程的图片、视频、动画图片等缓存在设备本地,便于提高用户浏览图片的流畅体验。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

官方网站:https://github.com/bumptech/glide

6、图片控件 - GifView

由于Android中并没有直接播放动画GIF图片的view,所以我们可以利用GifView控件来实现GIF图片展示功能。GifView的Jar包由四个类组成:

GifAction.java 主要用来监视GIF图片是否加载成功

GifFrame.java 里面三个成员:当前图片、延时、下张Frame的链接。

GifDecoder.java 解码线程类

GifView.java 是核心类,包含GifView构造方法,还可以设置图片源、延迟、绘制等。

官方网站:https://code.google.com/p/gifview/

7、下拉刷新 - Android PullToRefresh

Android PullToRefresh是一款可以再Android系统中下拉刷新的应用组件,可以很方便的让ListView拥有下拉刷新的功能。

整理的7款常用的开源免费的Android UI组件及官方下载地址

 

做Android开发的小伙伴们可以关注这个系列的文章,也可以在Android应用开发栏目中关注我们对Android项目的更新。

本教程采用图文结合的方式一步一步的整理Windows搭建Android开发环境详细步骤,对于刚入门想学Android开发新手来说最实用。

在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入 Android浪潮的朋友们,为了确保大家能顺利完成开发环境的搭建,文章写的尽量详细,希望对准备进入Android开发的朋友有帮助。

本教程将分为五个步骤来完成Android开发环境的部署。

第一步:安装JDK

要下载Oracle公司的JDK可以百度“JDK”进入Oracle公司的JDK下载页面(当前下载页面地址为http://www.oracle.com/technetwork/java/javase/downloads/index.html),选择自己电脑系统的对应版本即可。

【图解】如何在Windows搭建Android开发环境详细步骤

 

下载到本地电脑后双击进行安装。JDK默认安装成功后,会在系统目录下出现两个文件夹,一个代表jdk,一个代表jre。

【图解】如何在Windows搭建Android开发环境详细步骤

 

JDK的全称是Java SE Development Kit,也就是Java 开发工具箱。SE表示标准版。JDK是Java的核心,包含了Java的运行环境(Java Runtime Environment),一堆Java工具和给开发者开发应用程序时调用的Java类库。

我们可以打开jdk的安装目录下的Bin目录,里面有许多后缀名为exe的可执行程序,这些都是JDK包含的工具。通过第二步讲到的配置JDK的变量环境,我们可以方便地调用这些工具及它们的命令。

【图解】如何在Windows搭建Android开发环境详细步骤

 

JDK包含的基本工具主要有:

javac:Java编译器,将源代码转成字节码。

jar:打包工具,将相关的类文件打包成一个文件。

javadoc:文档生成器,从源码注释中提取文档。

jdb:debugger,调试查错工具。

java:运行编译后的java程序。

第二步:配置Windows上JDK的变量环境

很多刚学java开发的人按照网上的教程可以很轻松配置好Windows上JDK的变量环境,但是为什么要这么配置并没有多想。

我们平时打开一个应用程序,一般是通过桌面的应用程序图标双击或单击系统开始菜单中应用程序的菜单链接,无论是桌面的快捷图标还是菜单链接都包含了应用程序的安装位置信息,打开它们的时候系统会按照这些位置信息找到安装目录然后启动程序。

【图解】如何在Windows搭建Android开发环境详细步骤

 

知道了一个应用程序的安装目录位置,我们也可以通过命令行工具打开,如QQ的位置为:C:Program Files (x86)TencentQQQQProtectBin,QQ的应用程序名为为QQProtect.exe,那么我们打开命令行工具,然后进入到 “C:Program Files (x86)TencentQQQQProtectBin”目录,再输入“QQProtect”,即可运行qq。

【图解】如何在Windows搭建Android开发环境详细步骤

 

如果我们希望打开命令行工具后,直接输入“QQProtect”就能启动qq程序,而不是每次都进入qq的安装目录再启动,这个时候可以通过配置系统环境变量Path来实现。右击“我的电脑”,选择“属性”,在打开窗口中点击左边的“高级系统设置”,出现“系统属性”窗口,在“高级”选项卡下面点击 “环境变量”。

【图解】如何在Windows搭建Android开发环境详细步骤

 

编辑系统变量名“Path”,在“Path”变量(字符串内容)的后面追加qq的安装目录:;C:Program Files (x86)TencentQQQQProtectBin 注意追加的时候要在目录字符串的前面加个英文的分号;,英文分号是用来区分Path里面不同的路径。

【图解】如何在Windows搭建Android开发环境详细步骤

 

确定保存后,再回到命令窗口,不管在任何目录下,你只要输入qqprotect的命令,qq就会启动。

【图解】如何在Windows搭建Android开发环境详细步骤

 

通过启动qq的例子,我们总结下:当要求系统启动一个应用程序时,系统会先在当前目录下查找,如果没有则在系统变量Path指定的路径去查找。前面我们说了JDK包含了一堆开发工具,这些开发工具都在JDK的安装目录下,为了方便使用这些开发工具,我们有必要把JDK的安装目录设置了系统变量。这就是为什么在Windows安装了JDK后需要设置JDK的bin目录为系统环境变量的原因。

为了配置JDK的系统变量环境,我们需要设置三个系统变量,分别是JAVA_HOME,Path和CLASSPATH。下面是这三个变量的设置防范。

JAVA_HOME

先设置这个系统变量名称,变量值为JDK在你电脑上的安装路径:C:Program FilesJavajdk1.8.0_20。创建好后则可以利用%JAVA_HOME%作为JDK安装目录的统一引用路径。

Path

PATH属性已存在,可直接编辑,在原来变量后追加:;%JAVA_HOME%bin;%JAVA_HOME%jrebin 。

CLASSPATH

设置系统变量名为:CLASSPATH 变量值为:.;%JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar 。

注意变量值字符串前面有一个”.”表示当前目录,设置CLASSPATH 的目的,在于告诉Java执行环境,在哪些目录下可以找到您所要执行的Java程序所需要的类或者包。

第三步: 下载安装Eclipse

Eclipse为Java应用程序及Android开发的IDE(集成开发环境)。Eclipse不需要安装,下载后把解压包解压后,剪切eclipse文件夹到你想安装的地方,打开时设置你的工作目录即可。

Eclipse的版本有多个,这里选择下载Eclipse IDE for Java EE Developers这个版本。

【图解】如何在Windows搭建Android开发环境详细步骤

 

第四步:下载安装Android SDK

配置了JDK变量环境,安装好了Eclipse,这个时候如果只是开发普通的JAVA应用程序,那么Java的开发环境已经准备好了。我们要通过 Eclipse来开发Android应用程序,那么我们需要下载Android SDK(Software Development Kit)和在Eclipse安装ADT插件,这个插件能让Eclipse和Android SDK关联起来。

Android SDK提供了开发Android应用程序所需的API库和构建、测试和调试Android应用程序所需的开发工具。

打开http://developer.android.com/sdk/index.html,我们发现google提供了集成了Eclipse的Android Developer Tools,因为我们这次是已经下载了Eclipse,所以我们选择单独下载Android SDK。

下载后双击安装,指定Android SDK的安装目录,为了方便使用Android SDK包含的开发工具,我们在系统环境变量中的Path设置Android SDK的安装目录下的tools目录。

在Android SDK的安装目录下,双击“SDK Manager.exe”,打开Android SDK Manager,Android SDK Manage负责下载或更新不同版本的SDK包,我们看到默认安装的Android SDK Manager只安装了一个版本的sdk tools。

【图解】如何在Windows搭建Android开发环境详细步骤

 

打开Android SDK Manager,它会获取可安装的sdk版本,但是国内有墙,有时候会出现获取失败的情况。

【图解】如何在Windows搭建Android开发环境详细步骤

 

从弹出的log窗口中,我们可以看到连接 “https://dl-ssl.google.com”失败了。我们通过ping命令,发现果然网络不通。

【图解】如何在Windows搭建Android开发环境详细步骤

 

从万能的互联网上,我们找到了解决这个问题的方案,而且行之有效。

更改host文件

首先更改host文件,host文件在C:WindowsSystem32driversetc目录下,用记事本打开“hosts”文件,将下面两行信息追加到hosts文件末尾,保存即可。如果你的是windows8系统可能没有权限修改host文件,可以右击hosts文件,将 Users组设置为可对hosts文件完全控制的权限即可。

203.208.46.146 dl.google.com

203.208.46.146 dl-ssl.google.com

上面两行放在host文件的意思是将本地访问dl.google.com和dl-ssl.google.com定向到ip地址为203.208.46.146的服务器上。

【图解】如何在Windows搭建Android开发环境详细步骤

 

将Android SDK Manage上的https请求改成http请求

打开Android SDK Manager,在Tools下的 Options 里面,有一项 Force https://..sources to be fetched using http://… 将这一项勾选上,就可以了。

【图解】如何在Windows搭建Android开发环境详细步骤

 

再打开Android SDK Manager.exe,正常情况下就可以下载Android的各个版本的sdk了。你只需要选择想要安装或更新的安装包安装即可。这里是比较耗时的过程,还会出现下载失败的情况,失败的安装包只需要重新选择后再安装就可以了。

【图解】如何在Windows搭建Android开发环境详细步骤

 

第五步:为Eclipse安装ADT插件

前面我们已经配置好了java的开发环境,安装了开发Android的IDE,下载安装了Android SDK,但是Eclipse还没有和Android SDK进行关联,也就是它们现在是互相独立的,就好比枪和子弹分开了。为了使得Android应用的创建,运行和调试更加方便快捷,Android的开发团队专门针对Eclipse IDE定制了一个插件:Android Development Tools(ADT)。

下面是在线安装ADT的方法:

启动Eclipse,点击 Help菜单 -> Install New Software… ?,点击弹出对话框中的Add… 按钮。

【图解】如何在Windows搭建Android开发环境详细步骤

 

然后在弹出的对话框中的Location中输入:http://dl-ssl.google.com/android/eclipse/,Name可以输入ADT,点击“OK”按钮。

【图解】如何在Windows搭建Android开发环境详细步骤

 

在弹出的对话框选择要安装的工具,然后下一步就可以了。

【图解】如何在Windows搭建Android开发环境详细步骤

 

安装好后会要求你重启Eclipse,Eclipse会根据目录的位置智能地和它相同目录下Android sdk进行关联,如果你还没有通过sdk manager工具安装Android任何版本的的sdk,它会提醒立刻安装它们。

【图解】如何在Windows搭建Android开发环境详细步骤

 

如果Eclipse没有自动关联Android sdk的安装目录,那么你可以在打开的Eclipse选择 Window -> Preferences ,在弹出面板中就会看到Android设置项,填上安装的SDK路径,则会出现刚才在SDK中安装的各平台包,按OK完成配置。

【图解】如何在Windows搭建Android开发环境详细步骤

 

到这里,我们在windows上的Android上的开发环境搭建就完成了,这时候,你用Eclipse的File——》New——》Project…新建一个项目的时候,就会看到建立Android项目的选项了。

【图解】如何在Windows搭建Android开发环境详细步骤

 

Android为了安全起见,默认情况下任何应用创建的文件、sharedpreferences数据库都是私有的,其余进程不能正确访问,现在我们来讲解一下Android文件私有存储和私有文件资源文件的存取。
Android文件私有存储


首先内部存储路径为/data/data/youPackageName/,下面讲解的各路径都是基于你自己的应用的内部存储路径下。所有内部存储中保存的文件在用户卸载应用的时候会被删除。

一、 files

1. Context.getFilesDir(),该方法返回/data/data/youPackageName/files的File对象。
2. Context.openFileInput()与Context.openFileOutput(),只能读取和写入files下的文件,返回的是FileInputStream和FileOutputStream对象。
3. Context.fileList(),返回files下所有的文件名,返回的是String[]对象。
4. Context.deleteFile(String),删除files下指定名称的文件。

二、cache

Context.getCacheDir(),该方法返回/data/data/youPackageName/cache的File对象。

三、getDir

getDir(String name, int mode),返回/data/data/youPackageName/下的指定名称的文件夹File对象,如果该文件夹不存在则用指定名称创建一个新的文件夹。

Android私有文件资源文件的存取


Android有一套自己的安全模型, 可参见Android开发文档。当应用程序安装时就会分配一个userid,当应用要去访问其他资源比如文件时,需要userid匹配。默认情况下 ,任何应用创建的文件,数据库, sharedpreferences都应该是私有的(位于/data/data/your_project/files/),其余程序无法访问。除非在创建时指明是MODE_WORLD_READABLE 或者 MODE_WORLD_WRITEABLE,只要这样其余程序才能正确访问。因为有这种Android读写文件的方法在安全上有所保障,进程打开文件时Android要求检查进程的user id。所以不能直接用java的api来打开,因为java的io函数没有提这个机制 。有一个问题系统必须已经root,并且文件浏览器取得root权限否则通过文件浏览器是看不到那些目录的。

一、私有文件夹下的文件存取(./data/data/com.包名/files/下面,相当于程序工作目录)

无法用java的api直接打开程序私有的数据 ,默认路径为/data/data/your_project/files/,从sdcard中去读文件,首先要把文件通过android-sdk-windowstoolsadb.exe把本地计算机上的文件copy到sdcard上去,adb.exe push e:/Android.txt/sdcard/, 不可以用adb.exe push e:Android.txt sdcard,注意斜杠的,在linux下和winodws下是不一样的, 同样: 把仿真器上的文件copy到本地计算机上用: adb pull ./sdcard/Android.txt e:/ ,读取路径可以用“/sdcard/Android.txt”也可以用“mnt/sdcard/Android.txt”

如:

FileReader file = new FileReader("Android.txt");

这里特别强调私有数据!言外之意是如果某个文件或者数据不是程序私有的,既访问它时无须经过Android的权限检查,那么还是可以用java的io api来直接访问的。所谓的非私有数据是只放在sdcard上的文件或者数据,

可以用java的io api来直接打开sdcard上文件。

 如:

FileReader file = new FileReader("/sdcard/Android.txt");

如果要打开程序自己私有的文件和数据,那必须使用Activity提供openFileOutput和openFileInput方法。创建程序私有的文件,由于权限方面的要求,必须使用activity提供的Android读写文件方法。
如:

 代码如下 复制代码
 import java.io.FileInputStream;   
 import java.io.FileOutputStream;   
 import org.apache.http.util.EncodingUtils;   
    
 public void writeFileData(String fileName,String message){   
     try{   
      FileOutputStream fout = openFileOutput(fileName, MODE_PRIVATE); 
      //OutputStreamWriter outWriter = new OutputStreamWriter(fout);  
      byte [] bytes = message.getBytes();   
      fout.write(bytes);   
       fout.close();   
      }   
     catch(Exception e){   
      e.printStackTrace();   
     }   
 }      
    
 public String readFileData(String fileName){   
      String res="";   
      try{   
       //FileInputStream fin = openFileInput(fileName); 
       //InputStreamReader inReader = new InputStreamReader(fin); 
       //或者 
       FileInputStream fin = new FileInputStream(fileName); 
       int length = fin.available();   
       byte [] buffer = new byte[length];   
       fin.read(buffer);       
       res = EncodingUtils.getString(buffer, "UTF-8");   
       fin.close();       
      }   
      catch(Exception e){   
       e.printStackTrace();   
      }   
      return res;   
     }



二、从resource中的raw文件夹中获取文件并读取数据(资源文件只能读不能写,在"程序名resrawFileName.txt")

 代码如下 复制代码
public String getFromRaw(String fileName){   
    String res = "";   
       try{   
        InputStream in = getResources().openRawResource(R.raw.test1);    
        //资源在Testresrawtest1.txt 
        int length = in.available();         
        byte [] buffer = new byte[length];          
        in.read(buffer);   
        //依bbi.txt的编码类型选择合适的编码,如果不调整会乱码         
        res = EncodingUtils.getString(buffer, "UTF-8");  
        //res =EncodingUtils.getString(buffer, "BIG5"); 
        //res =EncodingUtils.getString(buffer, "UNICODE"); 
        in.close();              
       }   
       catch(Exception e){   
        e.printStackTrace();           
       }   
    return res ;   
   }


三、从asset中获取文件并读取数据(资源文件只能读不能写,在"程序名assertsFileName.txt")

 代码如下 复制代码
public String getFromAsset(String fileName){   
    String res="";   
    try{   
     InputStream in = getResources().getAssets().open(fileName);     
     int length = in.available();           
        byte [] buffer = new byte[length];          
        in.read(buffer);              
        res = EncodingUtils.getString(buffer, "UTF-8");       
    }   
    catch(Exception e){   
     e.printStackTrace();           
    }   
    return res;   
   } 
本教程我们为您介绍Android的第三方库so lib库如何远程http下载和动态注册,远程下载so库主要解决的是下载so存放的位置及读写权限,大家可以参考一下。

一、背景

在开发Android应用程序的实现,有时候需要引入第三方so lib库,但第三方so库比较大,例如开源第三方播放组件ffmpeg库, 如果直接打包的apk包里面, 整个应用程序会大很多.经过查阅资料和实验,发现通过远程下载so文件,然后再动态注册so文件时可行的。主要需要解决下载so文件存放位置以及文件读写权限问题。

二、主要思路

1、首先把so放到网络上面,比如测试放到:http://codestudy.sinaapp.com//lib/test.so
2、应用启动时,启动异步线程下载so文件,并写入到/data/data/packageName/app_libs目录下面
3、调用System.load 注册so文件。因路径必须有执行权限,我们不能加载SD卡上的so,但可以通过调用context.getDir("libs", Context.MODE_PRIVATE)把so文件写入到应用程序的私有目录/data/data/packageName/app_libs。

三、代码实现

1、网络下载so文件,并写入到应用程序的私有目录/data/data/PackageName/app_libs

 代码如下 复制代码
/**
 * 下载文件到/data/data/PackageName/app_libs下面
 * @param context
 * @param url
 * @param fileName
 * @return
 */
public static File downloadHttpFileToLib(Context context, String url, String fileName) {
    long start = System.currentTimeMillis();
    FileOutputStream outStream = null;
    InputStream is = null;
    File soFile = null;
    try {
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(url);
        HttpResponse response = client.execute(get);
        HttpEntity entity = response.getEntity();
        File dir = context.getDir("libs", Context.MODE_PRIVATE);
        soFile = new File(dir, fileName);
        outStream = new FileOutputStream(soFile);
        is = entity.getContent();
        if (is != null) {
            byte[] buf = new byte[1024];
            int ch = -1;
            while ((ch = is.read(buf)) > 0) {
                outStream.write(buf, 0, ch);
                //Log.d(">>>httpDownloadFile:", "download 进行中....");
            }
        }
        outStream.flush();
        long end = System.currentTimeMillis();
        Log.d(">>>httpDownloadFile cost time:",  (end-start)/1000 + "s");
        Log.d(">>>httpDownloadFile:", "download success");
        return soFile;
    } catch (IOException e) {
        Log.d(">>>httpDownloadFile:", "download failed" + e.toString());
        return null;
    } finally {
        if (outStream != null) {
            try {
                outStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



2、调用System.load 注册so文件

 代码如下 复制代码
new Thread(new Runnable() {
      @Override
      public void run() {
          File soFile = FileUtils.downloadHttpFileToLib(getApplicationContext(), "http://codestudy.sinaapp.com//lib/test.so", "test.so");
          if (soFile != null) {
            try {
                   Log.d(">>>loadAppFile load path:", soFile.getAbsolutePath());
                   System.load(soFile.getAbsolutePath());
             } catch (Exception e) {
                 Log.e(">>>loadAppFile load error:", "so load failed:" + e.toString());
             }
           }
      }
}).start();




四、需要解决的问题


1、so文件下载以及注册时机。测试发现libffmpeg.so  8M的文件单线程下载需要10-13s左右
2、so下载失败或者注册失败该怎么处理。例如so播放组件是否尝试采用android系统原生MediaPlayer进行播放
3、当初次so还没有下载完注册成功时,进入播放页面时,需要友好提示用户,比如loading 视频正在加载等等
4、无网络情况等等情况

五、说明

上面的demo经过3(2.3/4.2/4.4)实际机型测试可以正常使用,然后根据第四点列举问题完善以下,即可使用。

ThreadPoolExecutor是一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。

一、获取线程池的三种方法:

1、ExecutorService pool = Executors.newFixedThreadPool
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。

2、ExecutorService pool = Executors.newSingleThreadExecutor
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。

3、ExecutorService pool = Executors.newCachedThreadPool
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。

二、线程池类 java.util.concurrent.ThreadPoolExecutor讲解

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler)

参数说明

corePoolSize: 线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略

线程创建规则

一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。
当一个任务通过execute(Runnable)方法欲添加到线程池时:
l  如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2  如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
3  如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
4  如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
5  当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

核心和最大池大小

ThreadPoolExecutor 将根据 corePoolSize(参见 getCorePoolSize())和 maximumPoolSize(参见 getMaximumPoolSize())设置的边界自动调整池大小。当新任务在方法execute(java.lang.Runnable) 中提交时,如果运行的线程少于 corePoolSize,则创建新线程来处理请求,即使其他辅助线程是空闲的。如果运行的线程多于 corePoolSize 而少于 maximumPoolSize,则仅当队列满时才创建新线程。如果设置的 corePoolSize 和 maximumPoolSize 相同,则创建了固定大小的线程池。如果将 maximumPoolSize 设置为基本的无界值(如 Integer.MAX_VALUE),则允许池适应任意数量的并发任务。在大多数情况下,核心和最大池大小仅基于构造来设置,不过也可以使用setCorePoolSize(int) 和 setMaximumPoolSize(int) 进行动态更改。

创建新线程

使用 ThreadFactory 创建新线程。如果没有另外说明,则在同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态,等等。如果从 newThread 返回null 时 ThreadFactory 未能创建线程,则执行程序将继续运行,但不能执行任何任务。如果池中当前有多于 corePoolSize 的线程,则这些多出的线程在空闲时间超过 keepAliveTime 时将会终止(参见 getKeepAliveTime(java.util.concurrent.TimeUnit))。这提供了当池处于非活动状态时减少资源消耗的方法。如果池后来变得更为活动,则可以创建新的线程。也可以使用方法 setKeepAliveTime(long, java.util.concurrent.TimeUnit) 动态地更改此参数。使用 Long.MAX_VALUE TimeUnit.NANOSECONDS 的值在关闭前有效地从以前的终止状态禁用空闲线程。

排队

所有 BlockingQueue 都可用于传输和保持提交的任务。可以使用此队列与池大小进行交互:
A. 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
B. 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
C. 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。

execute()执行

execute()方法中,调用了三个私有方法
addIfUnderCorePoolSize():在线程池大小小于核心线程池大小的情况下,扩展线程池
addIfUnderMaximumPoolSize():在线程池大小小于线程池大小上限的情况下,扩展线程池
ensureQueuedTaskHandled():保证在线程池关闭的情况下,新加入队列的线程也能正确处理

线程池的停止和关闭

ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

[!--infotagslink--]

相关文章

  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • Vue组件跨层级获取组件操作

    这篇文章主要介绍了Vue组件跨层级获取组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-28
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • Vue实现动态查询规则生成组件

    今天我们来给大家介绍下在Vue开发中我们经常会碰到的一种需求场景,本文主要介绍了Vue动态查询规则生成组件,需要的朋友们下面随着小编来一起学习学习吧...2021-05-27
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • js组件SlotMachine实现图片切换效果制作抽奖系统

    这篇文章主要介绍了js组件SlotMachine实现图片切换效果制作抽奖系统的相关资料,需要的朋友可以参考下...2016-04-19
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • vue中使用element日历组件的示例代码

    这篇文章主要介绍了vue中如何使用element的日历组件,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-30
  • Android 实现钉钉自动打卡功能

    这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
  • Vue 过渡(动画)transition组件案例详解

    这篇文章主要介绍了Vue 过渡(动画)transition组件案例详解,非常不错,具有参考借鉴价值,需要的朋友参考下...2017-01-26
  • Android 开发之布局细节对比:RTL模式

    下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
  • Vue多选列表组件深入详解

    这篇文章主要介绍了Vue多选列表组件深入详解,这个是vue的基本组件,有需要的同学可以研究下...2021-03-03
  • Android中使用SDcard进行文件的读取方法

    首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20