首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

Android开发学习笔记:Activity的生命周期浅析

1.Android系统中Activity作为Activity栈(Stack)被管理的,大家都知道栈的特点是先进后出,所以当前活动的Activity处于栈顶,之前非活动的Activity被压入栈底,等待是否可能被恢复为活动状态。 Android API中所提供的Activity生命周期图: 2.下面的整个Activity生命周期中的所有方法,我们可以根据程序的需要来覆盖相应的方法: publicclassActivityextendsApplicationContext{ //创建的时候调用 protectedvoidonCreate(BundlesavedInstanceState); //启动的时候调用 protectedvoidonStart(); //重新启动的时候调用 protectedvoidonRestart(); //恢复的时候调用 protectedvoidonResume(); //暂停的时候调用 protectedvoidonPause(); //停止的时候调用 protectedvoidonStop(); //销毁的时候调用 protectedvoidonDestroy(); } onCreate(Bundle savedInstanceState):创建activity时调用。设置在该方法中,还以Bundle的形式提供对以前储存的任何状态的访问! onStart():activity变为在屏幕上对用户可见时调用。 onResume():activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用的) onPause():activity被暂停或收回cpu和其他资源时调用,该方法用于保存活动状态的,也是保护现场,压栈。 onStop():activity被停止并转为不可见阶段及后续的生命周期事件时调用。 onRestart():重新启动activity时调用。该活动仍在栈中,而不是启动新的活动 onDestroy():activity被完全从系统内存中移除时调用 3.下面通过实例来测试Activity的生命周期中各个方法的调用情况,将Activity的所有方法都覆盖,主要用Log打印输出信息,并通过日志(LogCat)方式来观察运行结果。Log.v(String tag, String msg); //Verbose Log.d(String tag, String msg); //Debug Log.i(String tag, String msg); //Info Log.w(String tag, String msg); //Warning Log.e(String tag, String msg); //Error tag类似标签,可以是任意字符串,通常可以使用类名+方法名, 主要是用来在查看日志时提供一个筛选条件。 下面的实例是测试Activity的生命周期中各个方法的调用情况: MainActivity.java packagecom.android.TestAvtivity.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ privateButtonbtn; privatestaticfinalStringTAG="MainActivity"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //输出日志 Log.i(TAG,"MainActivityonCreate--->"); btn=(Button)findViewById(R.id.Button1); btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //结束当前的Activity MainActivity.this.finish(); } }); } @Override //启动 protectedvoidonStart(){ super.onStart(); //输出日志信息 Log.i(TAG,"MainActivityonStart--->"); } @Override //重启 protectedvoidonRestart(){ super.onRestart(); //输出日志信息 Log.i(TAG,"MainActivityonRestart--->"); } @Override //恢复 protectedvoidonResume(){ super.onResume(); //输出日志信息 Log.i(TAG,"MainActivityonResume--->"); } @Override //暂停 protectedvoidonPause(){ super.onPause(); //输出日志信息 Log.i(TAG,"MainActivityonPause--->"); } @Override //停止 protectedvoidonStop(){ super.onStop(); //输出日志信息 Log.i(TAG,"MainActivityonStop--->"); } @Override //销毁 protectedvoidonDestroy(){ super.onDestroy(); //输出日志信息 Log.i(TAG,"MainActivityonDestroy--->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试Activit生命周期" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关闭Activity" /> </LinearLayout> 效果图: ①当启动程序时,日志的输出结果如下图所示,程序执行了onCreate()->onStart()->onResume三个方法。输出如下: MainActivity onCreate---> MainActivity onStart---> MainActivity onResume---> 注意:这里我是在选择了绿色的“+”,这时出现了下图的界面,之后我就在Filter Name上写入Test,by Log Tag上写入MainActivity,按OK保存,这时就能在LogCat上面筛选我们想要看到的信息了。 ②当按(返回键)或者按钮时,日志的输出结果如下图所示,程序先后调用了onPause( )->onStop( )->onDestory( )三个方法。 ③当按(Home键)时,日志的输出结果如下图所示,程序先后调用了onPause( )->onStop( )这两个方法,这时候应用程序并没有销毁。 ④当再次启动程序时,日志的输出结果如下图所示,程序先后调用了onRestart( )->onStart( )->onResume( )三个方法。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/636913

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

iOS开发socket程序被SIGPIPE信号Terminate的问题

以前在iphone上写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。 client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client 端时就产生Broken pipe 信号了。 对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。 如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。 我们可以调用系统的处理方法,也可以自定义处理方法。 以前不清楚的时候,程序莫名其妙的崩溃不了解,后来才了解到,在代码中进行了以下处理后app就不会崩溃了。 /***************************************************/ //设置不被SIGPIPE信号中断,物理链路损坏时才不会导致程序直接被Terminate //在网络异常的时候如果程序收到SIGPIRE是会直接被退出的。 struct sigaction sa; sa.sa_handler = SIG_IGN; sigaction( SIGPIPE, &sa, 0 ); /***************************************************/ 以下是从网络中整理的一些相关资料: 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE 9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGUSR1 17) SIGUSR2 18) SIGCHLD 19) SIGPWR 20) SIGWINCH 21) SIGURG 22) SIGIO 23) SIGSTOP 24) SIGTSTP 25) SIGCONT 26) SIGTTIN 27) SIGTTOU 28) SIGVTALRM 29) SIGPROF 30) SIGXCPU 31) SIGXFSZ 32) SIGWAITING 33) SIGLWP 34) SIGFREEZE 35) SIGTHAW 36) SIGCANCEL 37) SIGLOST 39) SIGRTMIN 40) SIGRTMIN+1 41) SIGRTMIN+2 42) SIGRTMIN+3 43) SIGRTMAX-3 44) SIGRTMAX-2 45) SIGRTMAX-1 46) SIGRTMAX 下面是一些信号说明 1) SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。 登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个 Session。当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。不过可以捕获这个信号,比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录, wget也 能继续下载。 此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。 2) SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。 3) SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。 4) SIGILL 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号。 5) SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用。 6) SIGABRT 调用abort函数生成的信号。 7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。 8) SIGFPE 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误。 9) SIGKILL 用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。 10) SIGUSR1 留给用户使用 11) SIGSEGV 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据. 12) SIGUSR2 留给用户使用 13) SIGPIPE 管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。 14) SIGALRM 时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号. 15) SIGTERM 程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。 17) SIGCHLD 子进程结束时, 父进程会收到这个信号。 如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸进程。这种情 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程 来接管)。 18) SIGCONT 让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作. 例如, 重新显示提示符 19) SIGSTOP 停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略. 20) SIGTSTP 停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号 21) SIGTTIN 当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN信号. 缺省时这些进程会停止执行. 22) SIGTTOU 类似于SIGTTIN, 但在写终端(或修改终端模式)时收到. 23) SIGURG 有”紧急”数据或out-of-band数据到达socket时产生. 24) SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变。 25) SIGXFSZ 当进程企图扩大文件以至于超过文件大小资源限制。 26) SIGVTALRM 虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间. 27) SIGPROF 类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的时间. 28) SIGWINCH 窗口大小改变时发出. 29) SIGIO 文件描述符准备就绪, 可以开始进行输入/输出操作. 30) SIGPWR Power failure 31) SIGSYS 非法的系统调用。 在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP 不能恢复至默认动作的信号有:SIGILL,SIGTRAP 默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ 默认会导致进程退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM 默认会导致进程停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU 默认进程忽略的信号有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH 此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;SIGCONT在进程挂起时是继续,否则是忽略,不能被阻塞。 大部分的信号都能中断socket程序。 本文转自 arthurchen 51CTO博客,原文链接:http://blog.51cto.com/arthurchen/736181,如需转载请自行联系原作者

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

WinForm自动化测试工具开发札记(4)

架构复用 这两天使用Win32 API参考对软件能用到的功能进行了一些小的尝试. 基本上没有什么太大的困难,只要努力,都能克服. 如果让这些功能散落在程序中,那么这个程序肯定写不出来.下面一段时间就开始设计类库了.使用接口/Abs类/类,把这些功能组织起来.昨天晚上在纸上大概画了画,画着画着才发现--咦,这不是跟.NET Framework的组织架构一样吗?呵呵,中微软的毒太深啦... 不过话又说回来,好的架构就应该复用. 又一个问题:是复用.NET Framework的架构,还是MFC的架构呢? 答案是:两者的"杂交品种". 1. .NET Framework的类种类丰富,适合测试WinForm上的各种控件. 2. 因为是在进行测试,所以.NET Framework的类中的"事件"成员的用处就不大了,去掉.这与MFC是一致的. 3. 正统的OO思想中本来也没有"事件"这个概念,微软自己加进去的.大概是沿袭了VB6的思想. 4. "属性"成员如果能去掉,也会去掉.降低程序的编写难度(其实也降低不了多少,搞不好程序不安全). 5. 正统的OO思想中也没有"属性"这个成员,也是微软自己加进去的.大概...(靠,哪儿来的拖鞋?) 6. 类与类(包括接口)间的继承关系,采用.NET Framework的,因为这个架构比MFC的更清晰. 本文转自 水之真谛 51CTO博客,原文链接:http://blog.51cto.com/liutiemeng/18758,如需转载请自行联系原作者

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

Android开发学习笔记:Service的简介和启动方式

一.Service的简介 1.Service 介绍和作用 Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当退出播放音乐的应用,如果不用Service,我 们就听不到歌了,所以这时候就得用到Service了。 2. Service生命周期 Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,当第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。 二.Service的启动方式 Service的有两种启动方式: Context.startService()和Context.bindService(),这两种方式对 Service生命周期的影响是不同的。 1.Context.startService()方式启动 ①Context.startService()方式的生命周期:启动时,startService –> onCreate() –> onStart() 停止时,stopService –> onDestroy() 如果调用者直接退出而没有停止Service,则Service 会一直在后台运行 Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。 ②Context.startService()方式启动 Service的方法: 下面是具体例子: MainActivity.java packagecom.android.service.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity { privateButtonstartBtn; privateButtonstopBtn; @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startBtn=(Button)findViewById(R.id.startBtn); stopBtn=(Button)findViewById(R.id.stopBtn); //添加监听器 startBtn.setOnClickListener(listener); stopBtn.setOnClickListener(listener); } //启动监听器 privateOnClickListenerlistener=newOnClickListener() { @Override publicvoidonClick(Viewv) { Intentintent=newIntent(MainActivity.this,ServiceDemo.class); switch(v.getId()) { caseR.id.startBtn: startService(intent); break; caseR.id.stopBtn: stopService(intent); break; default: break; } } }; } ServiceDemo.java packagecom.android.service.activity; importandroid.app.Service; importandroid.content.Intent; importandroid.os.IBinder; importandroid.util.Log; publicclassServiceDemoextendsService { privatestaticfinalStringTAG="Test"; @Override //Service时被调用 publicvoidonCreate() { Log.i(TAG,"ServiceonCreate--->"); super.onCreate(); } @Override //当调用者使用startService()方法启动Service时,该方法被调用 publicvoidonStart(Intentintent,intstartId) { Log.i(TAG,"ServiceonStart--->"); super.onStart(intent,startId); } @Override //当Service不在使用时调用 publicvoidonDestroy() { Log.i(TAG,"ServiceonDestroy--->"); super.onDestroy(); } @Override //当使用startService()方法启动Service时,方法体内只需写returnnull publicIBinderonBind(Intentintent) { returnnull; } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/startBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动Service" /> <Button android:id="@+id/stopBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="停止Service" /> </LinearLayout> 在AndroidManifest.xml文件中添加16~21行的声明 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.service.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <serviceandroid:name=".ServiceDemo"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </service> </application> </manifest> 效果图: 当点击按钮时,先后执行了Service中onCreate()->onStart()这两个方法,LogCat显示如下: 当点击按钮时,Service则执行了onDestroy()方法,LogCat显示如下: 当点击或按钮,进入Settings(设置)->Applications(应用)->Running Services(正在运行的服务)看一下我们新启动了的服务,效果图如下: 2 .Context.bindService() 方式启动: ①Context.bindService()方式的生命周期:绑定时,bindService -> onCreate() –> onBind() 调用者退出了,即解绑定时,Srevice就会unbindService –>onUnbind() –> onDestory() 用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。 ②Context.bindService()方式启动 Service的方法: 绑定Service需要三个参数:bindService(intent, conn, Service.BIND_AUTO_CREATE); 第一个:Intent对象 第二个:ServiceConnection对象,创建该对象要实现它的onServiceConnected()和onServiceDisconnected()来判断连接成功或者是断开连接 第三个:如何创建Service,一般指定绑定的时候自动创建 下面是具体的例子: MainActivity.java packagecom.android.bindservice.activity; importandroid.app.Activity; importandroid.app.Service; importandroid.content.ComponentName; importandroid.content.Intent; importandroid.content.ServiceConnection; importandroid.os.Bundle; importandroid.os.IBinder; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ //声明Button privateButtonstartBtn,stopBtn,bindBtn,unbindBtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //设置当前布局视图 setContentView(R.layout.main); //实例化Button startBtn=(Button)findViewById(R.id.startBtn1); stopBtn=(Button)findViewById(R.id.stopBtn2); bindBtn=(Button)findViewById(R.id.bindBtn3); unbindBtn=(Button)findViewById(R.id.unbindBtn4); //添加监听器 startBtn.setOnClickListener(startListener); stopBtn.setOnClickListener(stopListener); bindBtn.setOnClickListener(bindListener); unbindBtn.setOnClickListener(unBindListener); } //启动Service监听器 privateOnClickListenerstartListener=newOnClickListener(){ @Override publicvoidonClick(Viewv){ //创建Intent Intentintent=newIntent(); //设置Class属性 intent.setClass(MainActivity.this,BindService.class); //启动该Service startService(intent); } }; //停止Service监听器 privateOnClickListenerstopListener=newOnClickListener(){ @Override publicvoidonClick(Viewv){ //创建Intent Intentintent=newIntent(); //设置Class属性 intent.setClass(MainActivity.this,BindService.class); //启动该Service stopService(intent); } }; //连接对象 privateServiceConnectionconn=newServiceConnection(){ @Override publicvoidonServiceConnected(ComponentNamename,IBinderservice){ Log.i("Service","连接成功!"); } @Override publicvoidonServiceDisconnected(ComponentNamename){ Log.i("Service","断开连接!"); } }; //綁定Service监听器 privateOnClickListenerbindListener=newOnClickListener(){ @Override publicvoidonClick(Viewv){ //创建Intent Intentintent=newIntent(); //设置Class属性 intent.setClass(MainActivity.this,BindService.class); //绑定Service bindService(intent,conn,Service.BIND_AUTO_CREATE); } }; //解除绑定Service监听器 privateOnClickListenerunBindListener=newOnClickListener(){ @Override publicvoidonClick(Viewv){ //创建Intent Intentintent=newIntent(); //设置Class属性 intent.setClass(MainActivity.this,BindService.class); //解除绑定Service unbindService(conn); } }; } BindService.java packagecom.android.bindservice.activity; importandroid.app.Service; importandroid.content.Intent; importandroid.os.IBinder; importandroid.util.Log; publicclassBindServiceextendsService{ privatestaticfinalStringTAG="Test"; //返回null publicIBinderonBind(Intentintent){ Log.i(TAG,"ServiceonBind--->"); returnnull; } //Service创建时调用 publicvoidonCreate(){ Log.i(TAG,"ServiceonCreate--->"); } //当客户端调用startService()方法启动Service时,该方法被调用 publicvoidonStart(Intentintent,intstartId){ Log.i(TAG,"ServiceonStart--->"); } //当Service不再使用时调用 publicvoidonDestroy(){ Log.i(TAG,"ServiceonDestroy--->"); } //当解除绑定时调用 publicbooleanonUnbind(Intentintent){ Log.i(TAG,"ServiceonUnbind--->"); returnsuper.onUnbind(intent); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:text="启动Service" android:id="@+id/startBtn1" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:text="停止Service" android:id="@+id/stopBtn2" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:text="绑定Service" android:id="@+id/bindBtn3" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:text="解除绑定" android:id="@+id/unbindBtn4" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> 在AndroidManifest.xml文件中添加16~21行的声明 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.bindservice.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <serviceandroid:name=".BindService"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </service> </application> </manifest> 效果图: 当点击按钮时,先后执行了Service中onCreate()->onStart()这两个方法,LogCat显示如下: 当点击按钮,则Service执行了onUnbind()方法,LogCat显示如下: 当点击按钮,则Service执行了onUnbind()方法,LogCat显示如下: 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/647804

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

hadoop mapreduce开发实践之HDFS压缩文件(-cacheArchive)

1、分发HDFS压缩文件(-cacheArchive) 需求:wordcount(只统计指定的单词【the,and,had...】),但是该文件存储在HDFS上的压缩文件,压缩文件内可能有多个文件,通过-cacheArchive的方式进行分发; -cacheArchive hdfs://host:port/path/to/file.tar.gz#linkname.tar.gz #选项在计算节点上缓存文件,streaming程序通过./linkname.tar.gz的方式访问文件。 思路:reducer程序都不需要修改,mapper需要增加用来读取压缩文件的函数(或模块),运行streaming的时候需要使用-cacheArchive 指定hdfs上的文件; 1.1、 streaming命令格式(-cacheArchive) $HADOOP_HOME/bin/hadoop jar hadoop-streaming.jar \ -jobconf mapred.job.name="streaming_cacheArchive_demo" \ -jobconf mapred.job.priority=3 \ -jobconf mapred.compress.map.output=true \ -jobconf mapred.map.output.compression_codec=org.apache.hadoop.io.compress.GzipCodec \ -jobconf mapred.output.compress=true \ -jobconf mapred.out.compression.codec=org.apache.hadoop.io.compress.GzipCodec \ -input /input/ \ -output /output/ \ -mapper "python mapper.py whc.tar.gz" \ -reducer "python reducer.py" \ -cacheArchive "hdfs://master:9000/cache_file/wordwhite.tar.gz#whc.tar.gz" -file ./mapper.py \ -file ./reducer.py 1.2、mapper程序 #!/usr/bin/env python # -*- coding:utf-8 -*- import os import os.path import sys def getCachefile(filename): filelist = [] if os.path.isdir(filename): for root, dirs, files, in os.walk(filename): for name in files: filepath = root + '/' + name filelist.append(filepath) return filelist def readWordwhite(filename): wordset = set() for cachefile in getCachefile(filename): with open(cachefile, 'r') as fd: for line in fd: word = line.strip() wordset.add(word) return wordset def mapper(filename): wordset = readWordwhite(filename) for line in sys.stdin: line = line.strip() words = line.split() for word in words: if word != "" and (word in wordset): print "%s\t%s" %(word, 1) if __name__ == "__main__": if sys.argv[1]: file_fd = sys.argv[1] mapper(file_fd) 1.3、 reducer程序 #!/usr/bin/env python # -*- coding:utf-8 -*- import sys def reducer(): currentword = None wordsum = 0 for line in sys.stdin: wordlist = line.strip().split('\t') if len(wordlist) < 2: continue word = wordlist[0].strip() wordvalue = wordlist[1].strip() if currentword == None: currentword = word if currentword != word: print "%s\t%s" %(currentword, str(wordsum)) currentword = word wordsum = 0 wordsum += int(wordvalue) print "%s\t%s" %(currentword, str(wordsum)) if __name__ == "__main__": reducer() 1.4、上传wordwhite.tar.gz $ ls -R wordwhite wordwhite: wordwhite01 wordwhite02 wordwhite03 $ cat wordwhite/wordwhite0* have and had the in this or this to $ tar zcf wordwhite.tar.gz wordwhite $ hadoop fs -put wordwhite.tar.gz hdfs://localhost:9000/input/cachefile/ 1.5、 run_streaming程序 #!/bin/bash HADOOP_CMD="/home/hadoop/app/hadoop/hadoop-2.6.0-cdh5.13.0/bin/hadoop" STREAM_JAR_PATH="/home/hadoop/app/hadoop/hadoop-2.6.0-cdh5.13.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0-cdh5.13.0.jar" INPUT_FILE_PATH="/input/The_Man_of_Property" OUTPUT_FILE_PATH="/output/wordcount/WordwhiteCacheArchiveFiletest" $HADOOP_CMD fs -rmr -skipTrash $OUTPUT_FILE_PATH $HADOOP_CMD jar $STREAM_JAR_PATH \ -input $INPUT_FILE_PATH \ -output $OUTPUT_FILE_PATH \ -jobconf "mapred.job.name=wordcount_wordwhite_cacheArchivefile_demo" \ -mapper "python mapper.py WHF.gz" \ -reducer "python reducer.py" \ -cacheArchive "hdfs://localhost:9000/input/cachefile/wordwhite.tar.gz#WHF.gz" \ -file "./mapper.py" \ -file "./reducer.py" 1.6、执行程序 $ chmod +x run_streaming.sh $ ./run_streaming.sh rmr: DEPRECATED: Please use 'rm -r' instead. Deleted /output/wordcount/WordwhiteCacheArchiveFiletest 18/02/01 17:57:00 WARN streaming.StreamJob: -file option is deprecated, please use generic option -files instead. 18/02/01 17:57:00 WARN streaming.StreamJob: -cacheArchive option is deprecated, please use -archives instead. 18/02/01 17:57:00 WARN streaming.StreamJob: -jobconf option is deprecated, please use -D instead. 18/02/01 17:57:00 INFO Configuration.deprecation: mapred.job.name is deprecated. Instead, use mapreduce.job.name packageJobJar: [./mapper.py, ./reducer.py, /tmp/hadoop-unjar211766205758273068/] [] /tmp/streamjob9043244899616176268.jar tmpDir=null 18/02/01 17:57:01 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032 18/02/01 17:57:01 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032 18/02/01 17:57:03 INFO mapred.FileInputFormat: Total input paths to process : 1 18/02/01 17:57:03 INFO mapreduce.JobSubmitter: number of splits:2 18/02/01 17:57:04 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1516345010544_0030 18/02/01 17:57:04 INFO impl.YarnClientImpl: Submitted application application_1516345010544_0030 18/02/01 17:57:04 INFO mapreduce.Job: The url to track the job: http://localhost:8088/proxy/application_1516345010544_0030/ 18/02/01 17:57:04 INFO mapreduce.Job: Running job: job_1516345010544_0030 18/02/01 17:57:11 INFO mapreduce.Job: Job job_1516345010544_0030 running in uber mode : false 18/02/01 17:57:11 INFO mapreduce.Job: map 0% reduce 0% 18/02/01 17:57:20 INFO mapreduce.Job: map 50% reduce 0% 18/02/01 17:57:21 INFO mapreduce.Job: map 100% reduce 0% 18/02/01 17:57:27 INFO mapreduce.Job: map 100% reduce 100% 18/02/01 17:57:28 INFO mapreduce.Job: Job job_1516345010544_0030 completed successfully 18/02/01 17:57:28 INFO mapreduce.Job: Counters: 49 File System Counters FILE: Number of bytes read=113911 FILE: Number of bytes written=664972 FILE: Number of read operations=0 FILE: Number of large read operations=0 FILE: Number of write operations=0 HDFS: Number of bytes read=636501 HDFS: Number of bytes written=68 HDFS: Number of read operations=9 HDFS: Number of large read operations=0 HDFS: Number of write operations=2 Job Counters Launched map tasks=2 Launched reduce tasks=1 Data-local map tasks=2 Total time spent by all maps in occupied slots (ms)=12584 Total time spent by all reduces in occupied slots (ms)=4425 Total time spent by all map tasks (ms)=12584 Total time spent by all reduce tasks (ms)=4425 Total vcore-milliseconds taken by all map tasks=12584 Total vcore-milliseconds taken by all reduce tasks=4425 Total megabyte-milliseconds taken by all map tasks=12886016 Total megabyte-milliseconds taken by all reduce tasks=4531200 Map-Reduce Framework Map input records=2866 Map output records=14734 Map output bytes=84437 Map output materialized bytes=113917 Input split bytes=198 Combine input records=0 Combine output records=0 Reduce input groups=8 Reduce shuffle bytes=113917 Reduce input records=14734 Reduce output records=8 Spilled Records=29468 Shuffled Maps =2 Failed Shuffles=0 Merged Map outputs=2 GC time elapsed (ms)=390 CPU time spent (ms)=3660 Physical memory (bytes) snapshot=713809920 Virtual memory (bytes) snapshot=8331399168 Total committed heap usage (bytes)=594018304 Shuffle Errors BAD_ID=0 CONNECTION=0 IO_ERROR=0 WRONG_LENGTH=0 WRONG_MAP=0 WRONG_REDUCE=0 File Input Format Counters Bytes Read=636303 File Output Format Counters Bytes Written=68 18/02/01 17:57:28 INFO streaming.StreamJob: Output directory: /output/wordcount/WordwhiteCacheArchiveFiletest 1.7、 查看结果 $ hadoop fs -ls /output/wordcount/WordwhiteCacheArchiveFiletest Found 2 items -rw-r--r-- 1 hadoop supergroup 0 2018-02-01 17:57 /output/wordcount/WordwhiteCacheArchiveFiletest/_SUCCESS -rw-r--r-- 1 hadoop supergroup 68 2018-02-01 17:57 /output/wordcount/WordwhiteCacheArchiveFiletest/part-00000 $ hadoop fs -text /output/wordcount/WordwhiteCacheArchiveFiletest/part-00000 and 2573 had 1526 have 350 in 1694 or 253 the 5144 this 412 to 2782 以上就完成了分发HDFS上的压缩文件并指定单词的wordcount. 2、hadoop streaming 语法参考 http://blog.51cto.com/balich/2065419 本文转自 巴利奇 51CTO博客,原文链接:http://blog.51cto.com/balich/2067858

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

【Android 应用开发】Activity 状态保存 OnSaveInstanceState參数解析

作者:韩曙亮 转载请著名出处:http://blog.csdn.net/shulianghan/article/details/38297083 一. 相关方法简单介绍 1. 状态保存方法演示样例 package com.example.octopus_saveinstance; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } } 2. 相关方法介绍 (1) onCreate(Bundle savedInstanceState) 方法 Activity 创建时回调: 该方法会自己主动传入一个 Bundle 对象, 该 Bundle 对象就是上次被系统销毁时在onSaveInstanceState 或者onRestoreInstanceState 中保存的数据; --注意: 仅仅有是系统自己主动回收的时候才会保存 Bundle 对象数据; --Bundle 对象来源: onCreate() 方法中的 Bundle 对象參数, 是在 onSaveInstance() 或者 onRestoreInstanceState() 方法中保存的 Bundle 对象; . (2)onSaveInstanceState(Bundle outState) 方法 outState 參数作用: --数据保存: Activity 声明周期结束的时候, 须要保存 Activity 状态的时候, 会将要保存的数据使用键值对的形式 保存在 Bundle 对象中; --恢复数据: 在 Activity 的 onCreate()方法 创建 Activity 的时候会传入一个 Bundle 对象, 这个 Bundle 对象就是这个 outState 參数; 调用时机: Activity easy被销毁的时候调用, 注意是easy被销毁, 也可能没有销毁就调用了; --按下Home键: Activity 进入了后台, 此时会调用该方法; --按下电源键: 屏幕关闭, Activity 进入后台; --启动其他 Activity: Activity 被压入了任务栈的栈底; --横竖屏切换: 会销毁当前 Activity 并又一次创建; onSaveInstanceState方法调用注意事项: --用户主动销毁不会调用: 当用户点击回退键 或者 调用了 finish() 方法, 不会调用该方法; --调用时机不固定: 该方法一定是在 onStop() 方法之前调用, 可是不确定是在 onPause() 方法之前 还是 之后调用; --布局中组件状态存储: 每一个组件都 实现了 onSaveInstance() 方法, 在调用函数的时候, 会自己主动保存组件的状态, 注意, 仅仅有有 id 的组件才会保存; --关于默认的super.onSaveInstanceState(outState): 该默认的方法是实现 组件状态保存的; (3)onRestoreInstanceState(Bundle savedInstanceState) 方法 方法回调时机: 在 Activity 被系统销毁之后恢复 Activity 时被调用, 仅仅有销毁了之后重建的时候才调用, 假设内存充足, 系统没有销毁这个 Activity, 就不须要调用; --Bundle 对象传递: 该方法保存的 Bundle 对象在 Activity 恢复的时候也会通过參数传递到 onCreate() 方法中; --位于生命周期位置吧: 该方法在 onResume() 方法之前保存信息; 二 代码演示样例 Activity 主要代码: package com.example.octopus_saveinstance; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(savedInstanceState != null) System.out.println("onCreate() : " + savedInstanceState.getString("octopus")); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); System.out.println("onRestoreInstanceState() : " + savedInstanceState.getString("octopus")); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("octopus", "www.octopus.org.cn"); System.out.println("onSaveInstanceState() : save date www.octopus.org.cn"); } } 执行结果: 在执行的过程中 旋转屏幕; I/System.out( 8167): onSaveInstanceState() : save date www.octopus.org.cn I/System.out( 8167): onCreate() : www.octopus.org.cn I/System.out( 8167): onRestoreInstanceState() : www.octopus.org.cn 作者:韩曙亮 转载请著名出处:http://blog.csdn.net/shulianghan/article/details/38297083 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5346976.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

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

用户登录
用户注册