首页 文章 精选 留言 我的

精选列表

搜索[思考控制],共10005篇文章
优秀的个人博客,低调大师

重新思考“云爆发”

云计算世界中无所不有。云爆发能否使新包装卷土重来? 云爆发将面临一些现实情况: 将私有云系统的当前状态与大型超大规模厂商的特性和功能相比,私有云已不再是一回事。 企业需要在私有云和公共云上维护工作负载,才能使混合云爆发正常工作;本质上,使用两个不同的平台。 很明显,爆发式的混合云概念只会增加技术堆栈的复杂性和成本,从而使那些希望用最少的资源做更多的事情的企业广泛采用。 人们可能错过了几年前科技媒体的热情,云爆发是只有当本地云的容量用尽时才利用公共云的概念。企业以某种方式认为他们可以调用应用程序的基于公共云的部分,并且可以访问相同的数据而不会造成延迟。大多数情况下,它不起作用。 现在还有其他一些要说的关于2020年和2021年云爆裂的概念。 首先,当今存在一些类似于公共云的本地解决方案,因为它们是由公共云提供商出售的。包括谷歌、Microsoft和AWS在内的大型超大规模解决方案拥有传统数据中心中存在的硬件和软件解决方案。简而言之,这些是打包为设备的公共云解决方案的缩小版本。 考虑到本地平台和公共云平台都是专门为共同工作和良好发挥而设计的,因此使用这些解决方案可以实现云爆发。目标是通过使用这些本地解决方案作为中间步骤,最终将本地工作负载移动到公共云。 其次,边缘计算已经成为现实。连接到公共云的物联网设备的使用一直存在,但是作为设备和合法服务器的基于边缘的系统的正式使用是云计算架构时代精神的一部分。 这意味着边缘计算在公共云提供程序之外具有处理和数据存储功能,这些功能也专门用于与特定的公共云一起使用。而且,公共云提供商现在直接支持边缘。那些利用边缘计算基础设施的部署系统不必从头开始构建事物,而将公共云用于后端处理。 尽管有越来越多的架构模式看起来像是云爆发,但是这个概念实际上是关于分发处理和存储的,这并不是什么新鲜事物。在这里指出发生变化的目的实际上是指出事情确实发生了变化。这就是人们喜欢采用云计算开展业务的原因。 【责任编辑: 赵宁宁 TEL:(010)68476606】

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

pandas使用与思考

最近工作中,有一个场景,是从缓存中将数据读取出来,再聚合。 当时想到了三种方案: 使用dict的方式累加 使用数据库的临时表进行数据聚合 使用pandas汇总 方式一、以前使用php写过,考虑过不优雅,就放弃了 方式二、由于数据多,每次处理都要先写入数据库,然后再聚合,有点耗时,这方式也在线上测试了, 时间确实比较久。 所以采用了第三种方案: 我先贴出我的代码: 为了,剔除敏感信息,我做了混淆和简化 def sync_data_to_db(): """ 将缓存中的数据聚合后,持久化到db """ today = datetime.datetime.now().strftime('%Y-%m-%d') resp = data_api.get_data() data_frame = pd.DataFrame([], columns=['uid', 'age', 'country']) for line in resp.iter_lines(): user = json.loads(line.decode('utf-8')) uid = user.get('uid') age = user.get('age') countries = user.get('country', []) if countries: for i in countries: df = pd.DataFrame([[uid, age, country, i]], columns=['uid', 'age', 'country']) data_frame = data_frame.append(df) else: df = pd.DataFrame([[uid, age, country, 'Unknow']], columns=['uid', 'age', 'country']) data_frame = data_frame.append(df) data_frame = data_frame.groupby(['age', 'country'])\ .agg({'uid': {'user_count': len}}) UserCount.objects.filter(dt=today).delete() for i in data_frame.iterrows(): age, country = i[0] cnt = i[1].uid.user_count user = UserCount.objects.filter( dt=today, age=age, country=country ).first() if user: setattr(user, 'cnt', cnt) else: user = UserCount( dt=today, age=age, country=country cnt=cnt ) user.save() print(datetime.datetime.now()) 下面开始介绍pandas的使用 Pandas介绍 pandas是一个提供快速、可扩展和展现数据结构的Python库。目标是成为成为使用Python处理实践和实际数据分析的模块。并且想成为任何语言都能使用的最强大的可扩展的数据操作与分析开源工具。 主要的特性如下: 为浮点数和与浮点数精度丢失提供了简易的处理方法。 大数据(数字很大,不是通常意义的大数据)的处理。 自动而准确地处理数据队列。 功能强大。 能方便地转换不规则数据和差异数据。 智能地处理大数据集的切片、子集。 智能合并和连接数据集。 灵活地调整数据集。 从CSV、Excel和数据库中导入数据。 1、Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。 2、Pandas 是python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于2009年底开源出来,目前由专注于Python数据包开发的PyData开发team继续开发和维护,属于PyData项目的一部分。Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。 Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。panel data是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型。 3、数据结构: Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。 Time- Series:以时间为索引的Series。 DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。 Panel :三维的数组,可以理解为DataFrame的容器。 Pandas 有两种自己独有的基本数据结构。读者应该注意的是,它固然有着两种数据结构,因为它依然是 Python 的一个库,所以,Python 中有的数据类型在这里依然适用,也同样还可以使用类自己定义数据类型。只不过,Pandas 里面又定义了两种数据类型:Series 和 DataFrame,它们让数据操作更简单了。 三、 Pandas使用 1、导入pandas模块并使用别名,以及导入Series模块,以下使用基于本次导入。 In [1]: from pandas import Series In [2]: import pandas as pd 2、Series Series 就如同列表一样,一系列数据,每个数据对应一个索引值。 Series 就是“竖起来”的 list: In [3]: s = Series([1,2,3,4, "youdi", 'king', "world"]) In [4]: s Out[4]: 0 1 1 2 2 3 3 4 4 youdi 5 king 6 world dtype: object 另外一点也很像列表,就是里面的元素的类型,由你任意决定(其实是由需要来决定)。 这里,我们实质上创建了一个 Series 对象,这个对象当然就有其属性和方法了。比如,下面的两个属性依次可以显示 Series 对象的数据值和索引: In [5]: s.index Out[5]: RangeIndex(start=0, stop=7, step=1) In [6]: s.values Out[6]: array([1, 2, 3, 4, 'youdi', 'king', 'world'], dtype=object) 列表的索引只能是从 0 开始的整数,Series 数据类型在默认情况下,其索引也是如此。不过,区别于列表的是,Series 可以自定义索引: In [7]: s2 = Series(["youdi", 24, 'man'], index=['name', 'age', 'sex']) In [8]: s2 Out[8]: name youdi age 24 sex man dtype: object 每个元素都有了索引,就可以根据索引操作元素了。还记得 list 中的操作吗?Series 中,也有类似的操作。先看简单的,根据索引查看其值和修改其值: In [10]: s2.get('name') Out[10]: 'youdi' In [11]: s2.get('age') Out[11]: 24 In [12]: s2.get('sex') Out[12]: 'man' In [13]: s2['name'] = "liangchangyou" In [14]: s2['name'] Out[14]: 'liangchangyou' In [15]: s2 Out[15]: name liangchangyou age 24 sex man dtype: object 这是不是又有点类似 dict 数据了呢?的确如此。看下面就理解了。 读者是否注意到,前面定义 Series 对象的时候,用的是列表,即 Series() 方法的参数中,第一个列表就是其数据值,如果需要定义 index,放在后面,依然是一个列表。除了这种方法之外,还可以用下面的方法定义 Series 对象: In [16]: adobe = {"ps": 200, "ae": 300, 'pr': 400, "ai": 500} In [17]: s_adobe = Series(adobe) In [18]: s_adobe Out[18]: ae 300 ai 500 pr 400 ps 200 dtype: int64 现在是否理解为什么前面那个类似 dict 了?因为本来就是可以这样定义的。 这时候,索引依然可以自定义。Pandas 的优势在这里体现出来,如果自定义了索引,自定的索引会自动寻找原来的索引,如果一样的,就取原来索引对应的值,这个可以简称为“自动对齐”。 In [19]: s_ph = Series(adobe, index=["ps", "ae", "pr", "ai"]) In [20]: s_ph Out[20]: ps 200 ae 300 pr 400 ai 500 dtype: int64 In [21]: s_ph = Series(adobe, index=["ps", "ae", "pr", "ai", "maya"]) In [22]: In [22]: s_ph Out[22]: ps 200.0 ae 300.0 pr 400.0 ai 500.0 maya NaN dtype: float64 在 Pandas 中,如果没有值,都对齐赋给 NaN。 Pandas 有专门的方法来判断值是否为空。 In [23]: pd.isnull(s_ph) Out[23]: ps False ae False pr False ai False maya True dtype: bool 此外,Series 对象也有同样的方法: In [24]: s_ph.isnull() Out[24]: ps False ae False pr False ai False maya True dtype: bool 其实,对索引的名字,是可以从新定义的: In [25]: s_ph.index = ['python', 'php', 'c', 'golang', 'sql'] In [26]: s_ph Out[26]: python 200.0 php 300.0 c 400.0 golang 500.0 sql NaN dtype: float64 对于 Series 数据,也可以做类似下面的运算(关于运算,后面还要详细介绍): In [27]: s_ph * 3 Out[27]: python 600.0 php 900.0 c 1200.0 golang 1500.0 sql NaN dtype: float64 Series就先简要写到这,下面看pandas的另一种数据结构DataFrame. DataFrame DataFrame 是一种二维的数据结构,非常接近于电子表格或者类似 mysql 数据库的形式。它的竖行称之为 columns,横行跟前面的 Series 一样,称之为 index,也就是说可以通过 columns 和 index 来确定一个主句的位置。 首先来导入模块 In [28]: from pandas import Series,DataFrame In [30]: names = ['youdi', 'rino', 'jackson'] In [31]: age = [24, 35, 60] In [32]: sex = ['man', 'women', 'man'] In [33]: users = {"name": names, "age":age, "sex":sex} In [34]: df = DataFrame(users) In [35]: df Out[35]: age name sex 0 24 youdi man 1 35 rino women 2 60 jackson man 这是定义一个 DataFrame 对象的常用方法——使用 dict 定义。字典的“键”("name","age","sex")就是 DataFrame 的 columns 的值(名称),字典中每个“键”的“值”是一个列表,它们就是那一竖列中的具体填充数据。上面的定义中没有确定索引,所以,按照惯例(Series 中已经形成的惯例)就是从 0 开始的整数。从上面的结果中很明显表示出来,这就是一个二维的数据结构(类似 excel 或者 mysql 中的查看效果)。 上面的数据显示中,columns 的顺序没有规定,就如同字典中键的顺序一样,但是在 DataFrame 中,columns 跟字典键相比,有一个明显不同,就是其顺序可以被规定,向下面这样做: In [38]: df_1 = DataFrame(users, columns=['sex', 'name', 'age']) In [39]: df_1 Out[39]: sex name age 0 man youdi 24 1 women rino 35 2 man jackson 60 跟 Series 类似的,DataFrame 数据的索引也能够自定义 In [36]: df_1 = DataFrame(users, columns=['name', 'age', 'sex'], index=['I', 'II', 'III']) In [37]: df_1 Out[37]: name age sex I youdi 24 man II rino 35 women III jackson 60 man 定义 DataFrame 的方法,除了上面的之外,还可以使用“字典套字典”的方式。 In [40]: books = {'name': {1:"python", 2:"golang" }, "price":{1:60, 2:100}} In [41]: df_2 = DataFrame(books) In [42]: df_2 Out[42]: name price 1 python 60 2 golang 100 在字典中就规定好数列名称(第一层键)和每横行索引(第二层字典键)以及对应的数据(第二层字典值),也就是在字典中规定好了每个数据格子中的数据,没有规定的都是空。 DataFrame 对象的 columns 属性,能够显示素有的 columns 名称。并且,还能用下面类似字典的方式,得到某竖列的全部内容(当然包含索引): In [43]: books = {'name': {1:"python", 2:"golang" }, "price":{1:60}} In [44]: df_2 = DataFrame(books) In [45]: df_2 Out[45]: name price 1 python 60.0 2 golang NaN In [46]: df_2 = DataFrame(books, index=[1,2,3]) In [47]: df_2 Out[47]: name price 1 python 60.0 2 golang NaN 3 NaN NaN DataFrame 对象的 columns 属性,能够显示素有的 columns 名称。并且,还能用下面类似字典的方式,得到某竖列的全部内容(当然包含索引): In [48]: df_2.get("name") Out[48]: 1 python 2 golang 3 NaN Name: name, dtype: object 下面操作是给同一列赋值 In [54]: setattr(df_2, 'name', 'python') In [55]: df_2 Out[55]: name price 1 python 60.0 2 python NaN 3 python NaN In [56]: df_2['price'] = 100 In [58]: df_2 Out[58]: name price 1 python 100 2 python 100 3 python 100 也可以单独的赋值,除了能够统一赋值之外,还能够“点对点”添加数值,结合前面的 Series,既然 DataFrame 对象的每竖列都是一个 Series 对象,那么可以先定义一个 Series 对象,然后把它放到 DataFrame 对象中。如下: In [59]: df_1 Out[59]: sex name age 0 man youdi 24 1 women rino 35 2 man jackson 60 还可以更精准的修改数据吗?当然可以,完全仿照字典的操作: In [59]: df_1 Out[59]: sex name age 0 man youdi 24 1 women rino 35 2 man jackson 60 In [60]: df_1['age'][1] = 34 In [61]: df_1 Out[61]: sex name age 0 man youdi 24 1 women rino 34 2 man jackson 60 差不多简单的介绍了,由于df很像sql,所以类似sql都可以处理,数据的聚合,分类等。 我前一段时间学习了numpy,pandas,matplotlib等一些数据处理的工具, 我当时也没有想过后面会使用到,就是看看。 现在回头看,有时候遇到问题,很多内容都忘记了, 不能及时的写出代码,但是我可以找出解决的方案。对知识的广度以及视野也会影响你的职业素养。 这件事,让我想起一个关于读书的讨论: 读书的意义是什么? 这个问题,就好比——你吃的美食最终都会变成糟粕,那你为什么还要吃呢? 书,和食物,不也很相似吗? 一个,因为好吃。 另一个,它们精华的部分会变成营养被你身体吸收,保证我们的成长,是潜移默化的 读书也是类似的,当时是看不出成效的, 量变达到一定时候,就会质变。

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

BroadcastReceiver的思考(1)

作为四大组件,Broadcast Receiver 使用起来比较简单。有两种注册方式:1. 在AndroidManifest中注册。2. 在代码中直接注册,这种注册需要注意的一点是:当注册此Receiver的Activity退出的时候,一定要调用unregisterReceiver 方法,这个有点像Service的Bind。 第二种方式的示例代码如下: ?[Copy to clipboard]Downloadzuiniuwang.java *BroadCasterActivity.java *com.androidtest.broadcaster * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-6-8Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.broadcaster; importcom.androidtest.R; importandroid.app.Activity; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.View; importandroid.widget.Button; /** *ClassName:BroadCasterActivity *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-6-8 */ publicclassBroadCasterActivityextendsActivity{ privateBroadcastermyBroadcaster; @Override protectedvoidonCreate(BundlesavedInstanceState){ //TODOAuto-generatedmethodstub super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_broadcaster); myBroadcaster=newBroadcaster(); IntentFilterfilter=newIntentFilter(); filter.addAction("test"); this.registerReceiver(myBroadcaster,filter); Buttonbutton=(Button)this.findViewById(R.id.button1); button.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub Intentintent=newIntent("test"); BroadCasterActivity.this.sendBroadcast(intent); } }); } @Override publicvoidfinish(){ //TODOAuto-generatedmethodstub super.finish(); this.unregisterReceiver(myBroadcaster); } } classBroadcasterextendsBroadcastReceiver{ privatestaticfinalStringTAG="Broadcaster"; @Override publicvoidonReceive(Contextcontext,Intentintent){ //TODOAuto-generatedmethodstub Stringstring=intent.getAction(); Log.v(TAG,"Theactionis"+string); } } 当然我们也可以使用第一种方式,在AndroidManifest.xml定义,这样就定义了一个全局的receiver()和Activity <receiverandroid:name=".broadcaster.Broadcaster"> <intent-filter> <actionandroid:name="test"/> </intent-filter> </receiver> 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718307,如需转载请自行联系原作者

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

BroadcastReceiver的思考(3)

傻蛋提到了BroadcastReceiver是Android中最轻薄、最短小的组件,它的对象生命周期十分短暂,经过傻蛋测试在BroadcastReceiver中让线程睡眠10秒(Activity是5秒钟)的话,Android就会弹出错误(和Activity超时的错误相同),同时需要注意的是Activity、Service和BroadcastReceiver都是运行在本进程的主线程里面的。通过这个测试让傻蛋进一步产生了疑问,如果在Service中处理一个长时间的任务会怎么样? 启动一个Service,然后在Service的onCreate()方法中添加如下代码: try{ Log.v(TAG,"sleepstart….."); Thread.sleep(20000); Log.v(TAG,"sleepend….."); }catch(InterruptedExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } 单就是让Service睡眠20秒钟,我们会发现,sleep start…. 和 sleep end….这两个日志打印出来了,但是后台还会出现如下错误,前台弹出no response超时对话框。 当傻蛋在onCreate()中新启动一个线程来,睡眠时,程序正常。 所以总结一下:无论是 Activity、BroadcastReceiver还是Service,只要是有长时间处理的任务,就需要重新开一个线程来处理,为什么会这样?因为他们都是运行在主线程中的。 在使用BroadcastReceiver时还有一个我们需要注意的:在BroadcastReceiver的onReceive(Context context , Intent intent )这第一个context到底是哪一个context?是Activity还是Application?通过傻蛋测试发现: 如果你的BroadcastReceiver是通过在Activity中的this.registerReceiver(myBroadcaster, filter); 来注册的话,那么这个context就是这个Activity,而如果是通过AndroidManifest来注册的话,那么这个context就是:android.app.ReceiverRestrictedContext。 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/720191,如需转载请自行联系原作者

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

BroadcastReceiver的思考(2)

在使用Broadcast 时我们应该注意到,BroadcastReceiver的子类别都是无状态的类别,每次收到发送广播事件后,BroadcastReceiver都会创建一个新的对象,然后再执行onReceive()函数,当onReceive()函数执行完毕后,就立刻删掉该对象,下一次再收到此广播后,又会创建一个新的对象。所以说Broadcast组建是Android中最轻薄、最短小的组建。我们把上一篇文章的代码稍作一下修改,增加了一个static的变量numStatic ,和num变量 。代码如下: ?[Copy to clipboard] DownloadBroadcaster.java /** *Broadcaster.java *com.androidtest.broadcaster * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-6-9Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.broadcaster; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.util.Log; /** *ClassName:Broadcaster *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-6-9 */ publicclassBroadcasterextendsBroadcastReceiver{ privatestaticfinalStringTAG="Broadcaster"; privatestaticintnumStatic=100; privateintnum=100; @Override publicvoidonReceive(Contextcontext,Intentintent){ //TODOAuto-generatedmethodstub Stringstring=intent.getAction(); numStaticnumStatic=numStatic+50; num=100+50; Log.v(TAG,"Theactionis"+string+"StaticNumberis:"+numStatic +"Objectnumis:"+num); } } 多次发送广播,然后输出的结果如下,我们可以看到static Number 每次执行都会增加,而Object Num因为每次都要创建所以一直都是一个固定的值。 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718288,如需转载请自行联系原作者

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

BroadcastReceiver的思考(6)

上篇文章中我们谈到了,Service的远程沟通,既当Activity和Service不在一个进程中,它们之间是怎么相互通信的,不过只是停留在原理层面,今天傻蛋写了一个测试程序来进一步说明远程沟通机制。 Android框架的IPC沟通其实是依赖单一的IBinder接口,当Activity端呼叫IBinder接口的transact()函数时,就会透过IPC机制来呼叫远端的onTransact()函数。当调用transact函数之后,Android框架会根据线程的同步机制,等待远端的onTransact()函数执行完毕 并且返回,才继续向下面继续执行。傻蛋画了副图来进一步说明这个过程。 1. JavaBBinder是Android系统底层提供的类,其实它是个代理(代理模式),同时实现了IBinder接口,这样它onTransact()函数就能够调用myBinder的onTransact()函数 2. 当RemoteServiceTransactActivity需要夸进程来执行JavaBBinder的对象时,Android框架从RemoteServiceTransact所在的进程中启动一个线程Thread X来配合Thread A的执行,这样就变成进程内的通信了。 3. 通过这种远程代理的方式,使用者就会感觉到好像是在本地线程中执行程序一样了。 运行结果如下: 从结果我们可以看出Activity运行的线程名是main,Service运行的线程名也是main,不过和前面Activity的那个main不是一个,为了证明这一点我把它改名为main-changed,Binder所运行的线程名为Binder Thread #2 ,用来配合Activity主线程的远程调用。 测试代码如下: ?[Copy to clipboard] DownloadRemoteMusicService.java /** *RemoteMusicService.java *com.androidtest.service.mediaplayer * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-5-19Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.service; importcom.androidtest.R; importcom.androidtest.parcelable.ParcelableObject; importandroid.app.Service; importandroid.content.Intent; importandroid.media.MediaPlayer; importandroid.os.Binder; importandroid.os.IBinder; importandroid.os.Parcel; importandroid.os.Parcelable; importandroid.os.RemoteException; importandroid.util.Log; /** *ClassName:RemoteMusicService *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-5-19 */ publicclassRemoteServiceTransactextendsService{ privateIBindermBinder=null; privateStringreplyString; @Override publicvoidonCreate(){ //TODOAuto-generatedmethodstub super.onCreate(); mBinder=newmyBinder(); Thread.currentThread().setName("ServiceThreadName:"+ Thread.currentThread().getName()+"-chenaged"); } @Override publicIBinderonBind(Intentintent){ //TODOAuto-generatedmethodstub replyString=Thread.currentThread().getName(); returnmBinder; } publicclassmyBinderextendsBinder{ @Override protectedbooleanonTransact(intcode,Parceldata,Parcelreply, intflags)throwsRemoteException{ //TODOAuto-generatedmethodstub reply.writeString(replyString+"BinderThreadis:"+Thread.currentThread().getName()); returntrue; } } } ?[Copy to clipboard] DownloadRemoteServiceTransactActivity.java /** *RemoteServiceTransactActivity.java *com.androidtest.service * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-6-21Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.service; importcom.androidtest.service.mediaplayer.IMusicService; importandroid.app.Activity; importandroid.content.ComponentName; importandroid.content.Context; importandroid.content.Intent; importandroid.content.ServiceConnection; importandroid.os.Bundle; importandroid.os.IBinder; importandroid.os.Parcel; importandroid.util.Log; importandroid.view.View; importandroid.widget.Button; importandroid.widget.LinearLayout; importandroid.widget.TextView; /** *ClassName:RemoteServiceTransactActivity *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-6-21 */ publicclassRemoteServiceTransactActivityextendsActivity{ privatestaticfinalStringTAG=RemoteServiceTransactActivity.class.getSimpleName(); privatefinalintWC=LinearLayout.LayoutParams.WRAP_CONTENT; privatefinalintWP=LinearLayout.LayoutParams.FILL_PARENT; privateButtonbuttonRunService; privateTextViewtextView; privateIBinderiBinder; @Override protectedvoidonCreate(BundlesavedInstanceState){ //TODOAuto-generatedmethodstub super.onCreate(savedInstanceState); LinearLayoutlayout=newLinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); this.setTitle("TestRunService.."); //定义Button buttonRunService=newButton(this); buttonRunService.setId(1); buttonRunService.setText("RunService"); buttonRunService.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub ParcelsendParcel=Parcel.obtain(); ParcelreplyParcel=Parcel.obtain(); try{ iBinder.transact(2,sendParcel,replyParcel,0); //先打印出Activity的主线程名然后Service的主线程名更名然后返回,说明Service运行在不同 //的进程中 textView.setText("ActivityThreadNameis:"+Thread.currentThread().getName() +"and"+replyParcel.readString()); }catch(Exceptione){ e.printStackTrace(); } } }); //定义TextView textView=newTextView(this); textView.setText("Ready...."); //加入到Layout中 layout.addView(buttonRunService); layout.addView(textView); this.setContentView(layout); this.bindService(newIntent("com.androidtest.service.RemoteServiceTransact") ,myServiceConnection,Context.BIND_AUTO_CREATE); } privateServiceConnectionmyServiceConnection=newServiceConnection(){ @Override publicvoidonServiceConnected(ComponentNamename,IBinderbinder){ iBinder=binder; Log.d(TAG,"onServiceConnected"); } @Override publicvoidonServiceDisconnected(ComponentNamename){ Log.d(TAG,"onServiceDisconnected"); } }; } 同时在Android Manifest中需要这样来定义这个Service,以便它能够在不同的进程中运行。 <serviceandroid:enabled="true"android:process=":remote" android:name=".service.RemoteServiceTransact"> <intent-filter> <actionandroid:name="com.androidtest.service.RemoteServiceTransact"/> </intent-filter> </service> 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718292,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

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

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部分的功能。

用户登录
用户注册