首页 文章 精选 留言 我的

精选列表

搜索[MaaS平台],共10000篇文章
优秀的个人博客,低调大师

Android平台调用Web Service:螺纹的引入

文字连接 剩下的问题 MainActivity的onCreate方法中假设没有有这段代码: // 强制在UI线程中操作 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads().detectDiskWrites().detectNetwork() .penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath() .build()); 会报错误例如以下: FATAL EXCEPTION:main java.lang.NullPointerException atcom.example.demoservice.MainActivity.getRemoteInfo(MainActivity.java:91) atcom.example.demoservice.MainActivity$1.onClick(MainActivity.java:51) 这是由于android 3.0+以上 已经不建议在activity中加入耗时操作,要界面和数据脱离。4.0以上的通信都必须放到线程里去做,不能在UI线程。解决的方法是另起线程。假设一定要想在UI线程操作,就须要加入如上代码。 显然这样做是不可取的,由于通信消耗时间长,可能会让用户傻傻的等待。那么接下来就通过引入线程来解决问题。 通过Runnable接口和Thread类创建线程 我们能够用Runnable接口和Thread类创建线程。从而舍弃强制使用UI主线程的方式,代码例如以下(同一时候对代码进行了整理,把nameSpace等变量抽出来) public classMainActivity extends Activity { public static final String TAG ="webService_pj"; private EditText phoneSecEditText; private TextView resultView; private Button queryButton; @Override public void onCreate(BundlesavedInstanceState) { // StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder() // .detectDiskReads().detectDiskWrites().detectNetwork() // .penaltyLog().build()); // // StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder() // .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath() // .build()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); phoneSecEditText = (EditText)findViewById(R.id.phone_sec); resultView = (TextView)findViewById(R.id.result_text); queryButton = (Button)findViewById(R.id.query_btn); queryButton.setOnClickListener(newOnClickListener() { @Override public void onClick(View v) { Log.i(TAG,"MainActivity线程ID:"+Thread.currentThread().getId()); // 手机号码(段) String phoneSec =phoneSecEditText.getText().toString().trim(); // 简单推断用户输入的手机号码(段)是否合法 if("".equals(phoneSec) || phoneSec.length() < 7) { // 给出错误提示 phoneSecEditText.setError("您输入的手机号码(段)有误!"); phoneSecEditText.requestFocus(); // 将显示查询结果的TextView清空 resultView.setText(""); return; } // 命名空间 String nameSpace = "http://WebXml.com.cn/"; // 调用的方法名称 String methodName ="getMobileCodeInfo"; // EndPoint String endPoint = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"; // SOAP Action String soapAction = "http://WebXml.com.cn/getMobileCodeInfo"; // method params and values ArrayList<String> params= new ArrayList<String>(); ArrayList<Object> vals =new ArrayList<Object>(); params.add("mobileCode"); params.add("userId"); vals.add(phoneSec); vals.add(""); // 通过Runnable接口和Thread类 创建线程调用WebService newMyThread(nameSpace,methodName,endPoint,soapAction, params,vals).start(); //将WebService返回的结果显示在TextView中 resultView.setText(getResult()); } }); } //通过Runnable接口和Thread类,得到线程返回值 privateString result; publicString getResult(){ returnresult; } private class MyThread extends Thread { private String nameSpace; private String methodName; private String endPoint; private String soapAction; private ArrayList<String> params; private ArrayList<Object> vals; public MyThread(String nameSpace, String methodName, StringendPoint, String soapAction, ArrayList<String> params,ArrayList<Object> vals){ this.nameSpace = nameSpace; this.methodName = methodName; this.endPoint = endPoint; this.soapAction = soapAction; this.params = params; this.vals = vals; } @Override publicvoid run() { Log.i(TAG,"MyService线程ID:"+Thread.currentThread().getId()); result= getRemoteInfo(nameSpace, methodName, endPoint, soapAction,params,vals); } } /** *@MethodName : getRemoteInfo *@Description : 调用远程webservice方法 * @param nameSpace * @param methodName * @param endPoint * @param soapAction * @param params * @param vals * @return */ public String getRemoteInfo(StringnameSpace, String methodName, StringendPoint, String soapAction, ArrayList<String> params, ArrayList<Object>vals) { // 指定WebService的命名空间和调用的方法名 SoapObject rpc = newSoapObject(nameSpace, methodName); //设置需调用WebService接口须要传入的两个參数mobileCode、userId for (int i = 0; i < params.size();i++) { rpc.addProperty(params.get(i),vals.get(i)); } //生成调用WebService方法的SOAP请求信息,并指定SOAP的版本号 SoapSerializationEnvelope envelope =new SoapSerializationEnvelope(SoapEnvelope.VER10); envelope.bodyOut = rpc; // 设置是否调用的是dotNet开发的WebService // envelope.dotNet = true; // 等价于envelope.bodyOut = rpc; envelope.setOutputSoapObject(rpc); HttpTransportSE transport = newHttpTransportSE(endPoint); try { // 调用WebService transport.call(soapAction,envelope); } catch (Exception e) { e.printStackTrace(); } // 获取返回的数据 SoapObject object = (SoapObject)envelope.bodyIn; String result = ""; if (object != null) { // 获取返回的结果 result =object.getProperty(0).toString(); } return result; } } 通过线程进行通信。得到相同结果 出现新的问题 能够发现,运行线程中须要在线程中返回一个值,通过在run()中保存返回值。存储返回值的变量应该是MainActivity的成员变量。然后在主线程中用一个get方法取得该值。 可是run何时完毕是未知的。非常可能当第一次点击button后。依旧看不到结果,直到第二次或者很多其它才看到,所以我们须要一定的机制来保证。 而在Java se5就開始用Callable和Future来管理多线程了。能够解决问题。接下文。。 。 源代码下载 http://download.csdn.net/detail/tcl_6666/7365341 版权声明:本文博客原创文章,博客,未经同意,不得转载。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4732231.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

IBM大数据处理平台BigInsights(2)

1,在HDFS文件系统上创建test目录 hadoop fs -mkdir /user/biadmin/test 2,将文件copy到test目录下 hadoop fs -put /var/adm/ibmvmcoc-postinstall/BIlicense_en.txt /user/biadmin/test 3,查看test目录下是否多了这个文件 biadmin@bivm:/etc/ibmvmcoc-postinstall> hadoop fs -ls /user/biadmin/test Found 1 items -rw-r--r-- 1 biadmin biadmin 62949 2016-01-01 22:34 /user/biadmin/test/BIlicense_en.txt 4,运行一个简单的MapReduce程序 WordCount是用JAVA写的针对Hadoop MapReduce的一个小程序,用于统计文本中每个单词的出现次数,关于WordCount更多内容请参考-http://wiki.apache.org/hadoop/WordCount 执行程序是hadoop-example.jar,内容是在刚刚创建的test目录下,输出到WordCount_outpt子目录中。如果没有此目录,会自动创建。 biadmin@bivm:/etc/ibmvmcoc-postinstall>hadoop jar /opt/ibm/biginsights/IHC/hadoop-example.jar wordcount /user/biadmin/test WordCount_output 16/01/01 22:36:08 INFO input.FileInputFormat: Total input paths to process : 1 16/01/01 22:36:18 INFO mapred.JobClient: Running job: job_201601012120_0001 16/01/01 22:36:19 INFO mapred.JobClient: map 0% reduce 0% 16/01/01 22:37:58 INFO mapred.JobClient: map 100% reduce 0% 16/01/01 22:39:07 INFO mapred.JobClient: map 100% reduce 100% 16/01/01 22:39:14 INFO mapred.JobClient: Job complete: job_201601012120_0001 16/01/01 22:39:15 INFO mapred.JobClient: Counters: 29 16/01/01 22:39:15 INFO mapred.JobClient: File System Counters 16/01/01 22:39:15 INFO mapred.JobClient: FILE: BYTES_READ=33219 16/01/01 22:39:15 INFO mapred.JobClient: FILE: BYTES_WRITTEN=419738 16/01/01 22:39:15 INFO mapred.JobClient: HDFS: BYTES_READ=63073 16/01/01 22:39:15 INFO mapred.JobClient: HDFS: BYTES_WRITTEN=24073 16/01/01 22:39:15 INFO mapred.JobClient: org.apache.hadoop.mapreduce.JobCounter 16/01/01 22:39:15 INFO mapred.JobClient: TOTAL_LAUNCHED_MAPS=1 16/01/01 22:39:15 INFO mapred.JobClient: TOTAL_LAUNCHED_REDUCES=1 16/01/01 22:39:15 INFO mapred.JobClient: DATA_LOCAL_MAPS=1 16/01/01 22:39:15 INFO mapred.JobClient: SLOTS_MILLIS_MAPS=95300 16/01/01 22:39:15 INFO mapred.JobClient: SLOTS_MILLIS_REDUCES=50249 16/01/01 22:39:15 INFO mapred.JobClient: FALLOW_SLOTS_MILLIS_MAPS=0 16/01/01 22:39:15 INFO mapred.JobClient: FALLOW_SLOTS_MILLIS_REDUCES=0 16/01/01 22:39:15 INFO mapred.JobClient: org.apache.hadoop.mapreduce.TaskCounter 16/01/01 22:39:15 INFO mapred.JobClient: MAP_INPUT_RECORDS=755 16/01/01 22:39:15 INFO mapred.JobClient: MAP_OUTPUT_RECORDS=9865 16/01/01 22:39:15 INFO mapred.JobClient: MAP_OUTPUT_BYTES=102036 16/01/01 22:39:15 INFO mapred.JobClient: MAP_OUTPUT_MATERIALIZED_BYTES=33219 16/01/01 22:39:15 INFO mapred.JobClient: SPLIT_RAW_BYTES=124 16/01/01 22:39:15 INFO mapred.JobClient: COMBINE_INPUT_RECORDS=9865 16/01/01 22:39:15 INFO mapred.JobClient: COMBINE_OUTPUT_RECORDS=2322 16/01/01 22:39:15 INFO mapred.JobClient: REDUCE_INPUT_GROUPS=2322 16/01/01 22:39:15 INFO mapred.JobClient: REDUCE_SHUFFLE_BYTES=33219 16/01/01 22:39:15 INFO mapred.JobClient: REDUCE_INPUT_RECORDS=2322 16/01/01 22:39:15 INFO mapred.JobClient: REDUCE_OUTPUT_RECORDS=2322 16/01/01 22:39:15 INFO mapred.JobClient: SPILLED_RECORDS=4644 16/01/01 22:39:15 INFO mapred.JobClient: CPU_MILLISECONDS=22130 16/01/01 22:39:15 INFO mapred.JobClient: PHYSICAL_MEMORY_BYTES=538050560 16/01/01 22:39:15 INFO mapred.JobClient: VIRTUAL_MEMORY_BYTES=3549384704 16/01/01 22:39:15 INFO mapred.JobClient: COMMITTED_HEAP_BYTES=2097152000 16/01/01 22:39:15 INFO mapred.JobClient: File Input Format Counters 16/01/01 22:39:15 INFO mapred.JobClient: Bytes Read=62949 16/01/01 22:39:15 INFO mapred.JobClient: org.apache.hadoop.mapreduce.lib.output.FileOutputFormat$Counter 16/01/01 22:39:15 INFO mapred.JobClient: BYTES_WRITTEN=24073 会自动创建WordCount_output目录 biadmin@bivm:/etc/ibmvmcoc-postinstall> hadoop fs -ls WordCount_output Found 3 items -rw-r--r-- 1 biadmin biadmin 0 2016-01-01 22:39 WordCount_output/_SUCCESS drwx--x--x - biadmin biadmin 0 2016-01-01 22:36 WordCount_output/_logs -rw-r--r-- 1 biadmin biadmin 24073 2016-01-01 22:39 WordCount_output/part-r-00000 biadmin@bivm:~> hadoop fs -cat WordCount_output/*00 names, 1 national 1 nature 1 necessary 4 negligence 5 negligence, 4 negligence. 1 negligence; 2 neither 3 net 1 上面是用命令行方式来MapReduce,除此之外,IBM BigInsights还提供了基于Web界面的方式,打开Applications子选项,切换到Manage,可以看到预先定义的一些应用。在Test下面,有个WordCount应用,点开后选择“Deploy” 然切换到Run,可以看到已经有了WordCount这个应用, 选中WordCount,输入要统计文件所在的目录及输出目录,点击Run开始运行 同样地,也可以通过Web界面来操作HDFS文件系统,包括创建、删除、修改目录或者文件 用浏览器打开JobTracker(http://192.168.133.135:50030/jobtracker.jsp),显示出最近运行的MapReduce任务,点开JobID能看到更多详细信息。 所谓的JobTracker是一个master服务,Hadoop启动之后JobTracker接收Job,负责调度Job的每一个子任务task运行于TaskTracker上,并监控它们,如果发现有失败的task就重新运行它。 本文转自 taojin1240 51CTO博客,原文链接:http://blog.51cto.com/taotao1240/1735420,如需转载请自行联系原作者

优秀的个人博客,低调大师

高可用Hadoop平台-Oozie工作流

1.概述 在开发Hadoop的相关应用使用,在业务不复杂,任务不多的情况下,我们可以直接使用Crontab去完成相关应用的调度。今天给大家介绍的是统一管理各种调度任务的系统,下面为今天分享的内容目录: 内容介绍 Oozie Server 截图预览 下面开始今天的内容分享。 2.内容介绍 今天的内容不涉及Oozie的具体细节操作,它的工作流程在下一篇博客为大家详细介绍。今天主要给大家分享Oozie的作用,它的集成步骤等内容。 2.1 作用 Oozie它是一个开源的工作流调度系统,它可以管理逻辑复杂的多个Hadoop作业任务,按照指定的顺序将其进行协同工作。比如说,我们日常的工作场景: 收集数据到HDFS 编写MR去清洗数据,生成新的数据存放到指定的HDFS路径下 创建Hive表分区,并加载数据到对应的表分区 使用HQL进行业务指标统计,并将统计的结果输出到对应的Hive大表当中 对统计后的大表当中的数据进行数据导出共外界业务去调用使用 通过上述的日常工作流程,我们可以编写工作流系统,生成一个工作流实例,然后每天定时去运行实例即可。针对这样一种Hadoop的应用场景,Oozie能够简化我们的任务调度并执行。 2.2 基础环境 本次给大家分享的基础环境是: Name Value 操作系统 CentOS6.6 工作流 Oozie4.2 Hadoop 2.6 以上便是本篇博客需依赖的基础环境。另外还需要用到JDK,Maven,MySQL驱动文件等。 3.Oozie Server Oozie Server能够为我们提供便捷的Job管理功能,可以通过其可视化界面去管理Job的运行状态,当然也支持构建复杂的Hadoop Job流程,各个Job之间的依赖关系可以通过工作流进行配置,由Oozie Server统一去执行。 3.1 依赖包准备 Maven 下载安装Maven环境,命令如下所示: wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz tar -zxvf apache-maven-3.3.3-bin.tar.gz 接着添加环境变量,如下所示: export M2_HOME=/home/hadoop/maven-3.3.3 export PATH=$PATH:$ES_HOME/bin 然后输入一下命令使之立即生效: . /etc/profile 最后,我们输入 mvn -version 命令,若能现实对应的Maven版本号,即表示Maven环境集成OK。 MySQL 关于 MySQL 数据库的安装配置较为简单,这里就不多做赘述了。 Tomcat 由于Oozie会用其Web容器,这里需要安装Tomcat Web服务器,可以到Apache的官网下载对应的安装包,这里不多做赘述。 ExtJS工具包 在可视化会依赖该工具包,所以这里我们需要下载其工具,下载地址我们可以在Oozie的DG_QuickStart页面找到,如下图所示: 地址如下所示: wget http://dev.sencha.com/deploy/ext-2.2.zip Oozie 这里我们可以在Oozie的官网下载其安装包,下载地址: wget http://mirrors.cnnic.cn/apache/oozie/4.2.0/oozie-4.2.0.tar.gz 3.2 Oozie集成 在准备好环境后,接下来,我们去集成Oozie。首先,我们将下载的Oozie安装包进行解压,然后,使用Maven命令对其进行打包。操作命令如下所示: # 解压 tar -zxvf oozie-4.2.0.tar.gz # 进入 cd oozie-4.2.0 # 打包 mvn clean package assembly:single -DskipTests 注意:这里需要对pom文件进行修改,将JDK、Hadoop、HBase、Hive等组件的版本号进行统一,与你使用的版本号一致即可。 成功后出现以下图所示: 生成的路径地址如下所示: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0 此时,我们修改Oozie的环境变量,如下所示: export OOZIE_HOME=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0 export PATH=$PATH:$OOZIE_HOME/bin 接着,我们在$OOZIE_HOME目录下创建一个文件夹用于存放ExtJS和Hadoop的JAR文件,这里我们将前面下载的ExtJS的压缩包和Hadoop的Share目录下的JAR文件拷贝到libext文件夹下即可。由于,我们使用了MySQL来存储Oozie的元数据,所以需要用到MySQL的驱动包,因而,我们需要将MySQL的驱动包拷贝到libext目录下。 在准备完这些后,下面我们开始安装,命令如下所示: # 进入$OOZIE_HOME/bin目录 ./oozie-setup.sh prepare-war 生成以下信息,表示成功,内容如下所示: [hadoop@nna bin]$ ./oozie-setup.sh prepare-war setting CATALINA_OPTS="$CATALINA_OPTS -Xmx1024m" INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/commons-configuration-1.6.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-auth-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-common-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-common-2.6.0-tests.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-hdfs-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-hdfs-2.6.0-tests.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-hdfs-nfs-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-app-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-common-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-core-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-hs-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-hs-plugins-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-jobclient-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-jobclient-2.6.0-tests.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-client-shuffle-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-mapreduce-examples-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-nfs-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-api-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-applications-distributedshell-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-applications-unmanaged-am-launcher-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-client-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-common-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-registry-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-applicationhistoryservice-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-common-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-nodemanager-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-resourcemanager-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-tests-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/hadoop-yarn-server-web-proxy-2.6.0.jar INFO: Adding extension: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/libext/mysql-connector-java-5.1.32-bin.jar New Oozie WAR file with added 'ExtJS library, JARs' at /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/webapps/oozie.war INFO: Oozie is ready to be started 若失败,可根据提示做对应的处理。 这样,我们在/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/webapps目录下就生成了oozie.war文件。 3.3 配置Oozie 我们在$OOZIE_HOME/conf目录下修改oozie-site.xml文件,内容如下所示: <property> <name>oozie.service.JPAService.jdbc.driver</name> <value>com.mysql.jdbc.Driver</value> <description>JDBC driver class. </description> </property> <property> <name>oozie.service.JPAService.jdbc.url</name> <value>jdbc:mysql://nna:3306/oozie</value> <description>JDBC URL.</description> </property> <property> <name>oozie.service.JPAService.jdbc.username</name> <value>root</value> <description>DB user name.</description> </property> <property> <name>oozie.service.JPAService.jdbc.password</name> <value>root</value> <description>DB user password.</description> </property> 这里我们使用手动去创建数据库,oozie.service.JPAService.create.db.schema若为true属性,即表示去自动创建。手动创建脚本如下所示: CREATE DATABASE oozie; GRANT ALL ON oozie.* TO 'root'@'nna' IDENTIFIED BY 'root'; FLUSH PRIVILEGES; 然后,我们使用以下命令,生成数据表: #在$OOZIE_HOME/bin目录下操作 ./ooziedb.sh create -sqlfile oozie.sql -run 生成以下内容: [hadoop@nna bin]$ ./ooziedb.sh create -sqlfile oozie.sql -run setting CATALINA_OPTS="$CATALINA_OPTS -Xmx1024m" Validate DB Connection DONE DB schema does not exist Check OOZIE_SYS table does not exist DONE Create SQL schema DONE Create OOZIE_SYS table DONE Oozie DB has been created for Oozie version '4.2.0' The SQL commands have been written to: oozie.sql 若执行正常,会生成oozie.sql的脚本,如下图所示: 3.4 启动 接下来,我们去启动Oozie,命令如下所示: # 在$OOZIE_HOME/bin目录下 ./oozie-start.sh 正常启动内容如下所示: [hadoop@nna bin]$ ./oozie-start.sh WARN: Use of this script is deprecated; use 'oozied.sh start' instead Setting OOZIE_HOME: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0 Setting OOZIE_CONFIG: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/conf Sourcing: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/conf/oozie-env.sh setting CATALINA_OPTS="$CATALINA_OPTS -Xmx1024m" Setting OOZIE_CONFIG_FILE: oozie-site.xml Setting OOZIE_DATA: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/data Setting OOZIE_LOG: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/logs Setting OOZIE_LOG4J_FILE: oozie-log4j.properties Setting OOZIE_LOG4J_RELOAD: 10 Setting OOZIE_HTTP_HOSTNAME: nna Setting OOZIE_HTTP_PORT: 11000 Setting OOZIE_ADMIN_PORT: 11001 Setting OOZIE_HTTPS_PORT: 11443 Setting OOZIE_BASE_URL: http://nna:11000/oozie Setting CATALINA_BASE: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server Setting OOZIE_HTTPS_KEYSTORE_FILE: /home/hadoop/.keystore Setting OOZIE_HTTPS_KEYSTORE_PASS: password Setting OOZIE_INSTANCE_ID: nna Setting CATALINA_OUT: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/logs/catalina.out Setting CATALINA_PID: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/temp/oozie.pid Using CATALINA_OPTS: -Xmx1024m -Dderby.stream.error.file=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/logs/derby.log Adding to CATALINA_OPTS: -Doozie.home.dir=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0 -Doozie.config.dir=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/conf -Doozie.log.dir=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/logs -Doozie.data.dir=/home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/data -Doozie.instance.id=nna -Doozie.config.file=oozie-site.xml -Doozie.log4j.file=oozie-log4j.properties -Doozie.log4j.reload=10 -Doozie.http.hostname=nna -Doozie.admin.port=11001 -Doozie.http.port=11000 -Doozie.https.port=11443 -Doozie.base.url=http://nna:11000/oozie -Doozie.https.keystore.file=/home/hadoop/.keystore -Doozie.https.keystore.pass=password -Djava.library.path= Setting up oozie DB setting CATALINA_OPTS="$CATALINA_OPTS -Xmx1024m" Validate DB Connection DONE DB schema exists The SQL commands have been written to: /tmp/ooziedb-9100396876446618885.sql Using CATALINA_BASE: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server Using CATALINA_HOME: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server Using CATALINA_TMPDIR: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/temp Using JRE_HOME: /usr/java/jdk1.7 Using CLASSPATH: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/bin/bootstrap.jar Using CATALINA_PID: /home/hadoop/oozie-4.2.0/distro/target/oozie-4.2.0-distro/oozie-4.2.0/oozie-server/temp/oozie.pid 4.截图预览 然后,我们可以输入浏览地址,查看是否启动正常,如下图所示: 5.总结 关于Oozie的集成,会有点繁琐,本篇博客只是针对单独的Oozie去集成,后续博客会给大家介绍Oozie集成到Hadoop集群,以及相关工作流的用法介绍等。 6.结束语 这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉! 联系方式: 邮箱:smartloli.org@gmail.com Twitter: https://twitter.com/smartloli QQ群(Hadoop - 交流社区1): 424769183 温馨提示:请大家加群的时候写上加群理由(姓名+公司/学校),方便管理员审核,谢谢! 热爱生活,享受编程,与君共勉! 本文转自哥不是小萝莉博客园博客,原文链接:http://www.cnblogs.com/smartloli/,如需转载请自行联系原作者

优秀的个人博客,低调大师

百度云平台使用说明

当我们登陆之后,百度提供了在server上面的工作文件夹,而且是以/user/username方式命名,其username就是我们注冊的用户名,在百度网盘能够与HDFS分布式文件系统交互,相同在WEBserver上也能够与HDFS分布式系统交互,其方法是:在web shell 界面输入upload能够将用户文件上传到WEBserver上面用户相应的工作文件夹以下,然后我们能够使用hadoop fs -put test ./ 将WEBserver上的文件上传到HDFS分布式系统上,在WEBserver上面能够使用ls直接查看当前文件夹以下文件,能够使用hadoop fs -ls ./查看HDFS分布式系统上文件夹以下的文件。 主办方提供三种数据: 1.关键词数据集(文件为:hdfs://share/data/compad/keyword_class.txt) 2.关键词辅助信息数据集(文件为:hdfs://share/data/compad/keyword_titles.txt) 3.关键词与广告主关联关系数据集(文件为:hdfs://share/data/compad/keyword_users.txt) 使用例如以下命令将hdfs分布式系统上的文件下载到WEBserver: hadoop fs -get /share/data/compad/keyword_class.txt ./keyword_class.txt hadoop fs -get /share/data/compad/keyword_titles.txt ./keyword_titles.txt hadoop fs -get /share/data/compad/keyword_users.txt ./keyword_users.txt 下载之后其存放路径是: 当我想使用download命令将文件下载到本地时候。会提示文件超过大小,百度提供的文件大小权限是10M。超过10M文件无法下载。 相同我们还能够使用 hadoop fs -cp /share/data/compad/keyword_users.txt ./keyword_users.txt 将文件复制到HDFS分布式系统上面我们自己的用户文件夹下 如:我拷贝过之后,使用命令查看, hadoop fs -ls ./其所在路径是: 注意:两种方式拷贝的文件的目的路径是不同的。 Hadoop 运行jar文件命令:hadoop jar xxx.jar mainclass args hadoop jar ./My.jar My.jar 应该存在你的JobClient的个人文件夹下(/home/shijiebei2009/My.jar), 而不是你的hdfs个人文件夹下。 假设我运行位于HDFS分布式系统上的jar文件,那么会出现permission denied错误提示。 我们能够实现百度网盘与HDFS分布式文件系统进行交互。 从百度网盘到HDFS的文件传输 pan –put ./tupian.png ./test/tupian.png 从HDFS到百度网盘的文件传输 pan –get ./test/tupian.png./test/tupian.png 在用户的server上工作文件夹下存在一个文件index.html,用户输入hadoop fs –put index.html ./001,则会拷贝用户server上工作文件夹下的index.html。保存在用户在HDFS的工作文件夹下的001子文件夹中。 Question: 在从HDFS上向网盘转移文件时候,使用例如以下命令 pan -get /share/data/compad/keyword_class.txt ./keyword_class.txt 会出现 hdfs file not exist! 使用命令: pan -get /share/data/compad/keyword_titles.txt ./keyword_titles.txt 会出现: com.baidu.pcs.exception.PcsHttpException: org.apache.http.HttpException: IOException java.net.SocketException: Connection reset 当我在使用命令从网盘向HDFS上载文件时候,提示上载成功 可是在文件夹以下并不能找到我上载的文件 pan -get /user/shijiebei2009/keyword_class.txt ./keyword_class.txt pan -get /user/shijiebei2009/keyword_users.txt ./keyword_users.txt 这两条命令均能够成功将文件下载到百度网盘,可是例如以下命令下载还有一个文件时候 会提示文件过大,不能下载。 在使用例如以下程序訪问keyword_titles.txt时候,出现的错误提示 import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; public class hi { public static void main(String[] args) { ArrayList<String> keywordclass=new ArrayList<String>(); ArrayList<String> keywordtitles=new ArrayList<String>(); ArrayList<String> keywordusers=new ArrayList<String>(); keywordtitles = GetData("keyword_titles.txt"); // keywordclass = GetData("keyword_class.txt"); // keywordusers = GetData("keyword_users.txt"); // System.out.println(keywordclass.size()+" "+keywordtitles.size()+" "+keywordusers.size()); // System.out.println(keywordclass.size()); System.out.println(keywordtitles.size()); } public static ArrayList<String> GetData(String filename) { String dir=System.getProperty("user.dir")+"/"+filename; ArrayList<String> datalist=new ArrayList<String>(); File file=new File(dir); String line; try { BufferedReader reader=new BufferedReader( new FileReader(file)); while((line=reader.readLine())!=null) datalist.add(line); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(dir); return datalist; } } 当我想知道keyword_class.txt文件的大小的时候。程序结果例如以下: 程序输出的数据是行数 当我想知道keyword_users.txt文件的大小的时候,程序结果例如以下: 经过试验,假设我将程序中的dir改成例如以下形式 dir = “hdfs://share/data/compad/keyword_class.txt”; 即我要訪问HDFS分布式系统上的文件是訪问不了的,程序给出提演示样例如以下: 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5274628.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

android平台TextView使用ImageSpan画廊GIF图像

android-gif-drawable(https://github.com/koral--/android-gif-drawable/releases)开源项目---是一个蛮不错的android gif显示实现.本文在android-gif-drawable基础上介绍怎样实现TextView、EditText上展示Gif动态图。 网上有蛮多介绍这个框架使用的文章,比方http://www.open-open.com/lib/view/open1404888098200.html。 核心类GifDrawable间隔一定时间读取下一帧数据,然后运行invalidateSelf()----》CallBack::invalidateDrawable()---》View::verifyDrawable()和View::invalidate(),该帧数据刷新流程就运行结束。 而android-gif-drawable框架眼下已支持GifImageView、GifImageButton、GifTextView三个android widget,且 GifImageView、GifImageButton支持对src和backgroud设置Gif,而GifTextView对支持backgroud和CompoundDrawables设置Gif。 如今非常多app都支持Gif表情。但貌似还没有一个app对输入框(等)支持GIF。而基本全部的表情图片(包含Emoji)都是使用ImageSpan实现的。但默认的ImageSpan是无法支持GIF的。 參考android-gif-drawable框架中gif帧数据刷新流程,要支持GIF须要考虑并完毕以下三个操作: 1)对ImageSpan中的GifDrawable,何时设置其Callback,又何时清空该Callback,眼下TextView、ImageSpan和Spaned都没有设置Callback的地方。我们须要找一个合适的地方将TextView设置为GifDrawable的Callback; 2)在TextView::invalidateDrawable()中实现对GifDrawable的校验,即验证该GifDrawable是TextView的内容,须要刷新; 3)在TextView::invalidateDrawable()中实现怎样刷新TextView显示; 首先对于1)。我们參考下ImageView和TextView实现。ImageView的src drawable相应实现例如以下: /** * Sets a drawable as the content of this ImageView. * * @param drawable The drawable to set */ public void setImageDrawable(Drawable drawable) { if (mDrawable != drawable) { ... updateDrawable(drawable); ... } } private void updateDrawable(Drawable d) { if (mDrawable != null) { mDrawable.setCallback(null); unscheduleDrawable(mDrawable); } mDrawable = d; if (d != null) { d.setCallback(this); if (d.isStateful()) { d.setState(getDrawableState()); } d.setLevel(mLevel); d.setLayoutDirection(getLayoutDirection()); d.setVisible(getVisibility() == VISIBLE, true); mDrawableWidth = d.getIntrinsicWidth(); mDrawableHeight = d.getIntrinsicHeight(); applyColorMod(); configureBounds(); } else { mDrawableWidth = mDrawableHeight = -1; } }也就是说,ImageView在设置其src时。清空旧mDrawable的callback,然后将新设置的src drawable的callback设置为ImageView本身。 同理。TextView对于CompoundDrawables的callback处理也是在setCompoundDrawables()时。 而ImageSpan须要在什么时机设置GifDrawable的callback呢, public class GifImageSpan extends ImageSpan{ private Drawable mDrawable = null; public GifImageSpan(Drawable d) { super(d); mDrawable = d; } public GifImageSpan(Drawable d, int verticalAlignment) { super(d, verticalAlignment); mDrawable = d; } @Override public Drawable getDrawable() { return mDrawable; } } public class GifEditText extends EditText { private GifSpanChangeWatcher mGifSpanChangeWatcher; public GifEditText(Context context) { super(context); initGifSpanChangeWatcher(); } public GifEditText(Context context, AttributeSet attrs) { super(context, attrs); initGifSpanChangeWatcher(); } public GifEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initGifSpanChangeWatcher(); } private void initGifSpanChangeWatcher() { mGifSpanChangeWatcher = new GifSpanChangeWatcher(this); addTextChangedListener(mGifSpanChangeWatcher); } @Override public void setText(CharSequence text, BufferType type) { CharSequence oldText = null; try { //EditText的默认mText为""。是一个String。但getText()强转为Editable,尼玛。仅仅能try/catch了 oldText = getText(); //首先清空全部旧GifImageSpan的callback和oldText上的GifSpanChangeWatcher if (!TextUtils.isEmpty(oldText) && oldText instanceof Spannable) { Spannable sp = (Spannable) oldText; final GifImageSpan[] spans = sp.getSpans(0, sp.length(), GifImageSpan.class); final int count = spans.length; for (int i = 0; i < count; i++) { spans[i].getDrawable().setCallback(null); } final GifSpanChangeWatcher[] watchers = sp.getSpans(0, sp.length(), GifSpanChangeWatcher.class); final int count1 = watchers.length; for (int i = 0; i < count1; i++) { sp.removeSpan(watchers[i]); } } } catch (Exception e) { } if (!TextUtils.isEmpty(text)) { if (!(text instanceof Editable)) { text = new SpannableStringBuilder(text); } } if (!TextUtils.isEmpty(text) && text instanceof Spannable) { Spannable sp = (Spannable) text; //设置新text中全部GifImageSpan的callback为当前EditText final GifImageSpan[] spans = sp.getSpans(0, sp.length(), GifImageSpan.class); final int count = spans.length; for (int i = 0; i < count; i++) { spans[i].getDrawable().setCallback(this); } //清空新text上的GifSpanChangeWatcher final GifSpanChangeWatcher[] watchers = sp.getSpans(0, sp.length(), GifSpanChangeWatcher.class); final int count1 = watchers.length; for (int i = 0; i < count1; i++) { sp.removeSpan(watchers[i]); } if (mGifSpanChangeWatcher == null) { mGifSpanChangeWatcher = new GifSpanChangeWatcher(this); } //设置新text上的GifSpanChangeWatcher sp.setSpan(mGifSpanChangeWatcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE | (100 << Spanned.SPAN_PRIORITY_SHIFT)); } super.setText(text, type); } } public class GifSpanChangeWatcher implements SpanWatcher, TextWatcher{ private Drawable.Callback mCallback; public GifSpanChangeWatcher(Drawable.Callback callback) { mCallback = callback; } public void onSpanChanged(Spannable buf, Object what, int s, int e, int st, int en) { //do nothing } public void onSpanAdded(Spannable buf, Object what, int s, int e) { //设置callback if (what instanceof GifImageSpan) { ((GifImageSpan)what).getDrawable().setCallback(mCallback); } } public void onSpanRemoved(Spannable buf, Object what, int s, int e) { //清空callback if (what instanceof GifImageSpan) { ((GifImageSpan)what).getDrawable().setCallback(null); } } @Override public void afterTextChanged(Editable s) { if (s != null) { s.setSpan(this, 0, s.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE | (100 << Spanned.SPAN_PRIORITY_SHIFT)); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub } } 也就是,在setText()和onSpanAdded()、onSpanRemoved()中运行操作(1) 然后,对于2),相同參考ImageView和TextView @Override protected boolean verifyDrawable(Drawable dr) { return mDrawable == dr || super.verifyDrawable(dr); } @Override protected boolean verifyDrawable(Drawable who) { final boolean verified = super.verifyDrawable(who); if (!verified && mDrawables != null) { return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop || who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom || who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd; } return verified; }直接上代码 public class GifEditText extends EditText { private GifImageSpan getImageSpan(Drawable drawable) { GifImageSpan imageSpan = null; CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { if (text instanceof Spanned) { Spanned spanned = (Spanned) text; GifImageSpan[] spans = spanned.getSpans(0, text.length(), GifImageSpan.class); if (spans != null && spans.length > 0) { for (GifImageSpan span : spans) { if (drawable == span.getDrawable()) { imageSpan = span; } } } } } return imageSpan; } }getImageSpan()方法通过getSpans()获取全部的GifImageSpan。然后对照drawable,返回对应的GifImageSpan。 最后。操作3)更新View显示。相同參考下TextView @Override public void invalidateDrawable(Drawable drawable) { if (verifyDrawable(drawable)) { final Rect dirty = drawable.getBounds(); int scrollX = mScrollX; int scrollY = mScrollY; // IMPORTANT: The coordinates below are based on the coordinates computed // for each compound drawable in onDraw(). Make sure to update each section // accordingly. final TextView.Drawables drawables = mDrawables; if (drawables != null) { if (drawable == drawables.mDrawableLeft) { final int compoundPaddingTop = getCompoundPaddingTop(); final int compoundPaddingBottom = getCompoundPaddingBottom(); final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; scrollX += mPaddingLeft; scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightLeft) / 2; } else if (drawable == drawables.mDrawableRight) { final int compoundPaddingTop = getCompoundPaddingTop(); final int compoundPaddingBottom = getCompoundPaddingBottom(); final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; scrollX += (mRight - mLeft - mPaddingRight - drawables.mDrawableSizeRight); scrollY += compoundPaddingTop + (vspace - drawables.mDrawableHeightRight) / 2; } else if (drawable == drawables.mDrawableTop) { final int compoundPaddingLeft = getCompoundPaddingLeft(); final int compoundPaddingRight = getCompoundPaddingRight(); final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft; scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthTop) / 2; scrollY += mPaddingTop; } else if (drawable == drawables.mDrawableBottom) { final int compoundPaddingLeft = getCompoundPaddingLeft(); final int compoundPaddingRight = getCompoundPaddingRight(); final int hspace = mRight - mLeft - compoundPaddingRight - compoundPaddingLeft; scrollX += compoundPaddingLeft + (hspace - drawables.mDrawableWidthBottom) / 2; scrollY += (mBottom - mTop - mPaddingBottom - drawables.mDrawableSizeBottom); } } invalidate(dirty.left + scrollX, dirty.top + scrollY, dirty.right + scrollX, dirty.bottom + scrollY); } }计算compoundDrawable位置栏,然后运行invalidate。 对于GifEditText貌似也能够类似操作,依据GifImageSpan的start、end计算其位置栏,然后运行invalidate()。只是计算过程太过复杂了。只是android4.4的TextView提供这种方法void invalidateRegion(int start, int end, boolean invalidateCursor)方法用于刷新start和end之间的区域,但还是蛮复杂的看的人眼花缭乱。研究了下这种方法终于是由谁调用的。 invalidateRegion()<<---invalidateCursor()<<---spanChange()<<---ChangeWatcher::onSpanChanged()、ChangeWatcher::onSpanAdded()、ChangeWatcher::onSpanRemoved() 也就是说,仅仅要TextView内容中span发生变化都会触发invalidateRegion()来刷新相应区域和cursor。 @Override public void invalidateDrawable(Drawable drawable) { GifImageSpan imageSpan = getImageSpan(drawable); Log.e("", "invalidateDrawable imageSpan:" + imageSpan); if (imageSpan != null) { CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { if (text instanceof Editable) { Log.e("", "invalidateDrawable Editable:"); Editable editable = (Editable)text; int start = editable.getSpanStart(imageSpan); int end = editable.getSpanEnd(imageSpan); int flags = editable.getSpanFlags(imageSpan); editable.setSpan(imageSpan, start, end, flags); } } } else { super.invalidateDrawable(drawable); } }直接又一次设置该ImageSpan就可以触发ChangeWatcher::onSpanChanged()回调。也就会马上刷新其区域和cursor。 大功告成。执行ok。 上面是对EditText的实现,针对TextView实现略微有点差别 public class GifSpanTextView extends GifTextView { private GifSpanChangeWatcher mGifSpanChangeWatcher; public GifSpanTextView(Context context) { super(context); initGifSpanChangeWatcher(); } public GifSpanTextView(Context context, AttributeSet attrs) { super(context, attrs); initGifSpanChangeWatcher(); } public GifSpanTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initGifSpanChangeWatcher(); } private void initGifSpanChangeWatcher() { mGifSpanChangeWatcher = new GifSpanChangeWatcher(this); addTextChangedListener(mGifSpanChangeWatcher); } @Override public void setText(CharSequence text, BufferType type) { type = BufferType.EDITABLE; CharSequence oldText = getText(); if (!TextUtils.isEmpty(oldText) && oldText instanceof Spannable) { Spannable sp = (Spannable) oldText; final GifImageSpan[] spans = sp.getSpans(0, sp.length(), GifImageSpan.class); final int count = spans.length; for (int i = 0; i < count; i++) { spans[i].getDrawable().setCallback(null); } final GifSpanChangeWatcher[] watchers = sp.getSpans(0, sp.length(), GifSpanChangeWatcher.class); final int count1 = watchers.length; for (int i = 0; i < count1; i++) { sp.removeSpan(watchers[i]); } } if (!TextUtils.isEmpty(text) && text instanceof Spannable) { Spannable sp = (Spannable) text; final GifImageSpan[] spans = sp.getSpans(0, sp.length(), GifImageSpan.class); final int count = spans.length; for (int i = 0; i < count; i++) { spans[i].getDrawable().setCallback(this); } final GifSpanChangeWatcher[] watchers = sp.getSpans(0, sp.length(), GifSpanChangeWatcher.class); final int count1 = watchers.length; for (int i = 0; i < count1; i++) { sp.removeSpan(watchers[i]); } if (mGifSpanChangeWatcher == null) { mGifSpanChangeWatcher = new GifSpanChangeWatcher(this);; } sp.setSpan(mGifSpanChangeWatcher, 0, text.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE | (100 << Spanned.SPAN_PRIORITY_SHIFT)); } super.setText(text, type); } private GifImageSpan getImageSpan(Drawable drawable) { GifImageSpan imageSpan = null; CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { if (text instanceof Spanned) { Spanned spanned = (Spanned) text; GifImageSpan[] spans = spanned.getSpans(0, text.length(), GifImageSpan.class); if (spans != null && spans.length > 0) { for (GifImageSpan span : spans) { if (drawable == span.getDrawable()) { imageSpan = span; } } } } } return imageSpan; } @Override public void invalidateDrawable(Drawable drawable) { GifImageSpan imageSpan = getImageSpan(drawable); if (imageSpan != null) { CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { if (text instanceof Editable) { Editable editable = (Editable)text; int start = editable.getSpanStart(imageSpan); int end = editable.getSpanEnd(imageSpan); int flags = editable.getSpanFlags(imageSpan); editable.removeSpan(imageSpan); editable.setSpan(imageSpan, start, end, flags); } } } else { super.invalidateDrawable(drawable); } } } 设置其android:editable="true"或正上方setText(CharSequence text, BufferType type)将type设置BufferType.EDITABLE。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5045666.html,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册