首页 文章 精选 留言 我的

精选列表

搜索[垂直整合],共10009篇文章
优秀的个人博客,低调大师

spring-boot整合protobuf

简介:protobuf是Google的语言中立,平台中立,可扩展的机制,用于序列化结构化数据 - 想想XML,但更小,更快,更简单。您可以定义数据的结构化结构,然后使用特殊生成的源代码轻松地将结构化数据写入和读取各种数据流,并使用各种语言。1.在项目中导入依赖 <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.8.0</version> </dependency> 2.创建ReturnVO. proto文件 syntax = "proto3";

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

spring 整合spring data jpa

一、导入依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> 二、配置jpa <?xmlversion="1.0"encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"xmlns:cache="http://www.springframework.org/schema/cache"xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://cxf.apache.org/jaxwshttp://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-lazy-init="true"> <context:property-placeholderlocation="classpath:/config/config.properties"/> <!--数据源--> <beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource"> <propertyname="user"value="${jdbc.user}"/> <propertyname="password"value="${jdbc.password}"/> <propertyname="driverClass"value="${jdbc.driverClass}"/> <propertyname="jdbcUrl"value="${jdbc.jdbcUrl}"/> </bean> <!--JpaEntityManager配置--> <beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <propertyname="dataSource"ref="dataSource"/> <!--指定Jpa持久化实现厂商类,这里以Hibernate为例--> <propertyname="jpaVendorAdapter"ref="jpaVendorAdapter"></property> <!--指定Entity实体类包路径--> <propertyname="packagesToScan"value="com.web"/> <!--指定JPA属性;如Hibernate中指定是否显示SQL的是否显示、方言等--> <propertyname="jpaProperties"> <props> <!--命名规则My_NAME->MyName--> <propkey="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultComponentSafeNamingStrategy</prop> <!--打印sql语句--> <propkey="hibernate.show_sql">true</prop> <!--格式化sql语句--> <propkey="hibernate.format_sql">true</prop> </props> </property> </bean> <beanid="jpaVendorAdapter"class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!--自动检查注解的实体和数据表,如果数据库不存在的标,会根据实体自动生成--> <propertyname="generateDdl"value="false"/> <propertyname="database"value="HSQL"/> </bean> <beanid="jpaDialect"class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/> <!--配置事务--> <beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager"> <propertyname="entityManagerFactory"ref="entityManagerFactory"></property> </bean> <!--配置支持基于注解的事务--> <tx:annotation-driventransaction-manager="transactionManager"/> <!--重要配置:启用扫描并自动创建代理的功能--> <jpa:repositoriesbase-package="com.web"transaction-manager-ref="transactionManager"entity-manager-factory-ref="entityManagerFactory"/> </beans> 三、实现接口 (因为CrudRepository集成的是顶层接口Repository实现了简单的crud操作) publicinterfaceUserInfoRepositoryextendsCrudRepository<UserInfo,Long>{ } 四、注入使用 @Service publicclassUserInfoServiceImplimplementsUserInfoService{ @Autowired privateUserInfoRepositoryrepository; @Override publicList<UserInfo>findAll(){ return(List<UserInfo>)repository.findAll(); } }

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

Elasticsearch 与 Kafka 整合剖析

1.概述 目前,随着大数据的浪潮,Kafka 被越来越多的企业所认可,如今的Kafka已发展到0.10.x,其优秀的特性也带给我们解决实际业务的方案。对于数据分流来说,既可以分流到离线存储平台(HDFS),离线计算平台(Hive仓库),也可以分流实时流水计算(Storm,Spark)等,同样也可以分流到海量数据查询(HBase),或是及时查询(ElasticSearch)。而今天笔者给大家分享的就是Kafka 分流数据到ElasticSearch。 2.内容 我们知道,ElasticSearch是有其自己的套件的,简称ELK,即ElasticSearch,Logstash以及Kibana。ElasticSearch负责存储,Logstash负责收集数据来源,Kibana负责可视化数据,分工明确。想要分流Kafka中的消息数据,可以使用Logstash的插件直接消费,但是需要我们编写复杂的过滤条件,和特殊的映射处理,比如系统保留的`_uid`字段等需要我们额外的转化。今天我们使用另外一种方式来处理数据,使用Kafka的消费API和ES的存储API来处理分流数据。通过编写Kafka消费者,消费对应的业务数据,将消费的数据通过ES存储API,通过创建对应的索引的,存储到ES中。其流程如下图所示: 上图可知,消费收集的数据,通过ES提供的存储接口进行存储。存储的数据,这里我们可以规划,做定时调度。最后,我们可以通过Kibana来可视化ES中的数据,对外提供业务调用接口,进行数据共享。 3.实现 下面,我们开始进行实现细节处理,这里给大家提供实现的核心代码部分,实现代码如下所示: 3.1 定义ES格式 我们以插件的形式进行消费,从Kafka到ES的数据流向,只需要定义插件格式,如下所示: { "job": { "content": { "reader": { "name": "kafka", "parameter": { "topic": "kafka_es_client_error", "groupid": "es2", "bootstrapServers": "k1:9094,k2:9094,k3:9094" }, "threads": 6 }, "writer": { "name": "es", "parameter": { "host": [ "es1:9300,es2:9300,es3:9300" ], "index": "client_error_%s", "type": "client_error" } } } } } 这里处理消费存储的方式,将读和写的源分开,配置各自属性即可。 3.2 数据存储 这里,我们通过每天建立索引进行存储,便于业务查询,实现细节如下所示: public class EsProducer { private final static Logger LOG = LoggerFactory.getLogger(EsProducer.class); private final KafkaConsumer<String, String> consumer; private ExecutorService executorService; private Configuration conf = null; private static int counter = 0; public EsProducer() { String root = System.getProperty("user.dir") + "/conf/"; String path = SystemConfigUtils.getProperty("kafka.x.plugins.exec.path"); conf = Configuration.from(new File(root + path)); Properties props = new Properties(); props.put("bootstrap.servers", conf.getString("job.content.reader.parameter.bootstrapServers")); props.put("group.id", conf.getString("job.content.reader.parameter.groupid")); props.put("enable.auto.commit", "true"); props.put("auto.commit.interval.ms", "1000"); props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); consumer = new KafkaConsumer<String, String>(props); consumer.subscribe(Arrays.asList(conf.getString("job.content.reader.parameter.topic"))); } public void execute() { executorService = Executors.newFixedThreadPool(conf.getInt("job.content.reader.threads")); while (true) { ConsumerRecords<String, String> records = consumer.poll(100); if (null != records) { executorService.submit(new KafkaConsumerThread(records, consumer)); } } } public void shutdown() { try { if (consumer != null) { consumer.close(); } if (executorService != null) { executorService.shutdown(); } if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) { LOG.error("Shutdown kafka consumer thread timeout."); } } catch (InterruptedException ignored) { Thread.currentThread().interrupt(); } } class KafkaConsumerThread implements Runnable { private ConsumerRecords<String, String> records; public KafkaConsumerThread(ConsumerRecords<String, String> records, KafkaConsumer<String, String> consumer) { this.records = records; } @Override public void run() { String index = conf.getString("job.content.writer.parameter.index"); String type = conf.getString("job.content.writer.parameter.type"); for (TopicPartition partition : records.partitions()) { List<ConsumerRecord<String, String>> partitionRecords = records.records(partition); for (ConsumerRecord<String, String> record : partitionRecords) { JSONObject json = JSON.parseObject(record.value()); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); index = String.format(index, CalendarUtils.timeSpan2EsDay(json.getLongValue("_tm") * 1000L)); if (counter < 10) { LOG.info("Index : " + index); counter++; } for (String key : json.keySet()) { if ("_uid".equals(key)) { map.put("uid", json.get(key)); } else { map.put(key, json.get(key)); } list.add(map); } EsUtils.write2Es(index, type, list); } } } } } 这里消费的数据源就处理好了,接下来,开始ES的存储,实现代码如下所示: public class EsUtils { private static TransportClient client = null; static { if (client == null) { client = new PreBuiltTransportClient(Settings.EMPTY); } String root = System.getProperty("user.dir") + "/conf/"; String path = SystemConfigUtils.getProperty("kafka.x.plugins.exec.path"); Configuration conf = Configuration.from(new File(root + path)); List<Object> hosts = conf.getList("job.content.writer.parameter.host"); for (Object object : hosts) { try { client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(object.toString().split(":")[0]), Integer.parseInt(object.toString().split(":")[1]))); } catch (Exception e) { e.printStackTrace(); } } } public static void write2Es(String index, String type, List<Map<String, Object>> dataSets) { BulkRequestBuilder bulkRequest = client.prepareBulk(); for (Map<String, Object> dataSet : dataSets) { bulkRequest.add(client.prepareIndex(index, type).setSource(dataSet)); } bulkRequest.execute().actionGet(); // if (client != null) { // client.close(); // } } public static void close() { if (client != null) { client.close(); } } } 这里,我们利用BulkRequestBuilder进行批量写入,减少频繁写入率。 4.调度 存储在ES中的数据,如果不需要长期存储,比如:我们只需要存储及时查询数据一个月,对于一个月以前的数据需要清除掉。这里,我们可以编写脚本直接使用Crontab来进行简单调用即可,脚本如下所示: #!/bin/sh # <Usage>: ./delete_es_by_day.sh kafka_error_client logsdate 30 </Usage>echo "<Usage>: ./delete_es_by_day.sh kafka_error_client logsdate 30 </Usage>" index_name=$1 daycolumn=$2 savedays=$3 format_day=$4 if [ ! -n "$savedays" ]; then echo "Oops. The args is not right,please input again...." exit 1 fi if [ ! -n "$format_day" ]; then format_day='%Y%m%d' fi sevendayago=`date -d "-${savedays} day " +${format_day}` curl -XDELETE "es1:9200/${index_name}/_query?pretty" -d " { "query": { "filtered": { "filter": { "bool": { "must": { "range": { "${daycolumn}": { "from": null, "to": ${sevendayago}, "include_lower": true, "include_upper": true } } } } } } } }" echo "Finished." 然后,在Crontab中进行定时调度即可。 5.总结 这里,我们在进行数据写入ES的时候,需要注意,有些字段是ES保留字段,比如`_uid`,这里我们需要转化,不然写到ES的时候,会引发冲突导致异常,最终写入失败。 6.结束语 这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉 联系方式: 邮箱:smartloli.org@gmail.com Twitter: https://twitter.com/smartloli QQ群(Hadoop - 交流社区1): 424769183 温馨提示:请大家加群的时候写上加群理由(姓名+公司/学校),方便管理员审核,谢谢! 热爱生活,享受编程,与君共勉! 作者:哥不是小萝莉 [关于我][犒赏] 出处:http://www.cnblogs.com/smartloli/ 转载请注明出处,谢谢合作!

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

5G技术可提升众多垂直行业的能源效率

ICT行业对温室气体排放的贡献不到全球总量的2%,而在OECD(经合组织)国家中,约占总增加值的6%,在中国GDP中所占的比重超过7%。这一相对比率意味着仅让电信网络提高能源效率只会对气候变化产生较小的影响。 5G只有对其他行业的能源效率产生重大影响时,才会对全球能源使用产生有意义的影响。 在本文中,我们将探讨能源、医疗保健和制造业等排放量较高的行业,以证明可量化5G所带来的收益。这三个部门约占全球温室气体排放量的61%,但占全球GDP的38%,如图1所示。同时,还将探讨智慧城市和交通用例的定性案例研究。 图1:2017年全球GDP和温室气体排放量的行业 如以下小节所述,我们的建模和分析表明,5G可能对这些行业产生重大的环境影响(以减少温室气体的方式衡量),从而实现了没有5G不可能或无法承受的新运营方式。 我们还发现,在最迫切需要能源效率转型的这些领域中,如果将5G与云,人工智能和物联网等其他技术以及其他变化(例如采用可再生能源)相结合,则可以发挥显著作用。 5G与人工智能、物联网和云等ICT技术的结合可以提高其他行业的能效 如今,为减少5G能耗,人们正在做出巨大努力。尽管5G网络本身必须具有能源效率,但真正意义上的变革性影响将出现在5G可以使许多其他行业(包括能耗水平远高于电信行业的其他行业)以更节能的方式运行时。根据ITU的SMART 2020报告发现,到2020年,所有行业的ICT能源效率规模相当于全球所有排放量的15%。 欧盟的数据表明(见图5.2),能源的最大消费领域是交通、工业和家庭,因此,如果技术能够提高这些生活领域的效率并减少排放,那么对气候变化的影响将大于部署5G网络本身对气候变化的影响。 图2:欧盟各行业的能源消耗 这种效果取决于对流程和行为的改变,这些改变由高容量、无处不在和低延迟的移动网络支持。5G网络如何减少行业能耗的一些示例包括: 支持所有部门的智能能源管理,包括通过5G连接增强智能电网和智能电表系统,基于IoT的监控以及支持AI的分析,以支持诸如机器、城市基础设施或家用设备。 由于改善了会议模式(包括虚拟现实)而减少了办公空间或差旅需求,这意味着员工可以在任何地方工作。 通过持续监控整个供应链中的货物、车辆和设施,减少浪费和主动计划,实现了高效的“及时”供应链。 智能管理智慧城市中载有人员和货物的车辆的行驶,以减少不必要的行程。 支持建筑物和基础设施中的智能电源管理。 这些因素是通过结合高速、低延迟5G和其他技术(例如AI / ML和边缘云)而实现的。它们与数十亿个已连接的IoT设备一起,支持超连接性,从而使用户能够以较低的能源开销以新方式进行交互。例如,无需出差。这种技术组合也为网络切片提供了基础,网络切片可精确分配特定行业和特定任务所需的网络和计算资源,只要它们是必需的:一旦任务结束,虚拟切片资源便可以关闭并在其他地方重复使用。切片将使行业拥有适合其要求的专用虚拟网络,而无需过度配置它们,从而浪费资源。 与其他技术结合使用时,以下是5G支持效果的一些示例。 英国政府已承诺长期减少能源消耗和碳排放。运输部已将车辆监控和能源效率确定为车队管理部门的关键问题。为了解决这些问题并优化能耗,政府启动了多项远程信息处理计划。例如,远程信息处理系统已部署在600辆警用车辆中,以测量燃料消耗和温室气体排放。通过使用这些系统产生的好处包括:1)在确定车辆利用率之后减少120辆车辆; 2)减少温室气体排放,节省燃料成本超过382000英镑。 根据政府的倡议和企业环境的可持续发展目标,台湾一家大型金融机构制定了一个目标,即在2016年至2050年之间将其温室气体排放量减少30%。为提高能源效率和提高运营的可持续性,公司已实施遍布其189个分支机构的支持AI的建筑能源优化解决方案。该解决方案成功地将每个分支的平均用电量减少了5%至15%。 2018年,每名员工的能源消耗也下降了9.1%。 斯洛文尼亚的一家水泥生产厂面临着对其设施和基础设施进行调整以符合欧洲能源相关法规要求的挑战。该工厂每年消耗超过90GWh的电力和8GWh的天然气。 2017年,它启动了一项能源管理项目,其中涉及基于无线LoRaWAN技术的智能能源解决方案。该解决方案提高了每个生产过程中工厂能耗的可见性,并实现了更精确的实时监控。部署解决方案后,工厂成功减少了温室气体排放和能源消耗。 香港的一家房地产开发商制定了十年计划,以促进可持续发展,目标是到2025年将温室气体排放量减少35%。它与AI系统和平台提供商合作,建造了具有AI功能的“绿色建筑”在城市。基于AI的数据平台可通过对公用事业系统的预测使用和自动化操作以及预测维护来实现节能。该建筑已成功减少了与其日常运营相关的能耗。

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

Elasticsearch大咖说 | Elasticsearch 在手机垂直搜索业务的应用创新

Elasticsearch 作为一个分布式、高扩展、实时的搜索与数据分析引擎,因其轻量级、稳定、可靠、快速等特性受到越来越多开发者的青睐,在搜索、日志分析、运维监控和安全分析等领域得到广泛应用。阿里云 Elasticsearch 技术团队,深度采访了来自阿里巴巴、vivo、携程、eBay 等知名公司的技术专家,推出了 Elasticsearch 大咖说系列专题,为广大开发者提供技术入门与进阶的经验分享,以及最佳应用实践参考。 分享嘉宾 杨振涛 vivo 互联网搜索引擎架构师 vivo 是一个专注于智能手机领域的知名品牌,而 vivo 互联网为 vivo 智能手机用户提供极致的互联网产品和服务。从 Elasticsearch 2.1.1版本开始,到目前,vivo 互联网已经使用了 200 多个 Elasticsearch 集群来支撑全球 2

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

Android 自定义垂直,旋转,圆形进度提示 自定义Seekbar

SeekBar是用来调节参数值的,系统默认的一般都不太适合我们,需要我们自定义, 里面也有一个RxJava背压的具体应用 废话不多说,看图 package com.example.helang.seekbar; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.ObservableEmitter; import io.reactivex.ObservableOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.functions.Consumer; /** * 自定义拖动seekBar */ public class CustomSeekBar extends View { private static final String TAG = "CustomSeekBar"; private static final int radius = 65;//中间圆形进度条的半径 private static final int thumbSize = 200; private int backgroundLineSize = 10;//背景线的宽度 private int foregroundLineSize = 18;//进度的宽度 private int lineSize;//整条背景线的长度 private float touchY; private Bitmap thumbBitmap; private Paint paint; private Paint circlePaint;//绘制进度条的paint private RectF backgroundLineRect = new RectF();//背景矩形 private RectF foregroundLineRect = new RectF();//进度矩形 private float currentDegrees = 0;//当前的进度,百分比例,不带百分号 private OnProgressListener onProgressListener; public void setOnProgressListener(OnProgressListener onProgressListener) { this.onProgressListener = onProgressListener; } public CustomSeekBar(Context context) { this(context,null); } public CustomSeekBar(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public CustomSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initBitmap(); initPaint(); } /** * init bitmap */ private void initBitmap(){ thumbBitmap = drawableToBitmap(thumbSize,getResources().getDrawable(R.drawable.circle)); } /** * init paint */ private void initPaint() { paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setTextSize(10); //初始化圆形进度条的Paint circlePaint = new Paint(); circlePaint.setAntiAlias(true); // 抗锯齿 circlePaint.setDither(true); // 防抖动 circlePaint.setStrokeWidth(10); circlePaint.setShader(null); // 清除上一次的shader circlePaint.setStyle(Paint.Style.STROKE); // 设置绘制的圆为空心 circlePaint.setShadowLayer(10, 10, 10, Color.RED); circlePaint.setColor(Color.BLUE); // 设置圆弧的颜色 circlePaint.setStrokeCap(Paint.Cap.ROUND); // 把每段圆弧改成圆角的 } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawLine(canvas); drawThumb(canvas); drawCircleProgress(canvas); } /** * draw circle * @param canvas */ private void drawCircleProgress(Canvas canvas){ RectF oval = new RectF(thumbSize/2-radius, thumbSize/2-radius, thumbSize/2+radius, thumbSize/2+radius); // 圆的外接正方形 float alphaAngle = currentDegrees * 360.0f / 100 * 1.0f; // 计算每次画圆弧时扫过的角度,这里计算要注意分母要转为float类型,否则alphaAngle永远为0 canvas.drawArc(oval, -90, alphaAngle, false, circlePaint); } /** * draw thumb * @param canvas */ private void drawThumb(Canvas canvas){ //添加旋转,Matrix是Bitmap旋转的关键,用于bitmap一些补间动画的操作 canvas.translate((getWidth()-thumbSize)/2,(100-currentDegrees)/100*lineSize); Matrix matrix = new Matrix(); matrix.setRotate(currentDegrees*10,thumbSize/2,thumbSize/2); canvas.drawBitmap(thumbBitmap,matrix,null);//旋转背景 } /** * draw lines * @param canvas */ private void drawLine(Canvas canvas){ //绘制背景线 backgroundLineRect.set((getWidth()-backgroundLineSize)/2,thumbSize/2, (getWidth()+backgroundLineSize)/2, getParentHeight()-thumbSize/2); lineSize = getParentHeight() - thumbSize;//去掉被thumb挡住的一部分长度 paint.setColor(Color.rgb(61,82,89)); canvas.drawRoundRect(backgroundLineRect, backgroundLineSize/2, backgroundLineSize/2, paint); //绘制进度线 paint.setColor(Color.rgb(90,189,220));//进度线的颜色 foregroundLineRect.set((getWidth()-foregroundLineSize)/2, (getParentHeight()-thumbSize)*(100-currentDegrees)/100+thumbSize/2, (getWidth()+foregroundLineSize)/2,getParentHeight()-thumbSize/2); canvas.drawRoundRect(foregroundLineRect,foregroundLineSize/2,foregroundLineSize/2,paint); } /** * get ParentHeight * @return */ private int getParentHeight(){ return getHeight(); } @Override public boolean dispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) return true; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touchY = event.getRawY();//记录开始的Y值 break; case MotionEvent.ACTION_MOVE: currentDegrees += (touchY-event.getRawY())*1f/(getParentHeight())*100.0f;//当前进度值(100为满) if (currentDegrees > 100){//超出去的不计算,默认为100 currentDegrees = 100; } if (currentDegrees<0){//超出去的不计算,默认为0 currentDegrees = 0; } if (observableEmitter != null){//使用背压发送 observableEmitter.onNext(1); }else {//直接发送 sendProgress(); } touchY = event.getRawY(); invalidate(); break; case MotionEvent.ACTION_CANCEL: break; case MotionEvent.ACTION_UP: break; } return true; } private ObservableEmitter<Integer> observableEmitter; /** *增加背压,防止发射拖动的事件过快,导致内存溢出 */ public void addBackPressure(){ Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { observableEmitter = emitter; } }).sample(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { sendProgress(); } }); } /** * 发送进度 */ private void sendProgress(){ if (onProgressListener != null){ onProgressListener.onProgress(currentDegrees); } } /** * 设置当前进度 * @param currentDegrees */ public void setCurrentDegrees(float currentDegrees){ this.currentDegrees = currentDegrees; invalidate(); } public interface OnProgressListener{ void onProgress(float progress); } /** * make a drawable to a bitmap * @param drawable drawable you want convert * @return converted bitmap */ private Bitmap drawableToBitmap(int size, Drawable drawable) { Bitmap bitmap = null; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; bitmap = bitmapDrawable.getBitmap(); if (bitmap != null && bitmap.getHeight() > 0) { Matrix matrix = new Matrix(); float scaleHeight = size * 1.0f / bitmapDrawable.getIntrinsicHeight(); matrix.postScale(scaleHeight, scaleHeight); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return bitmap; } } bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } } Demo地址:https://github.com/helang1991/SeekBar 喜欢的就加个Star,谢谢

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册