首页 文章 精选 留言 我的

精选列表

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

使用天天模拟器开发Android应用

下载天天模拟器 天天模拟器官网 配置ADB环境变量 新建系统环境变量"ANDROID"内容为: D:\BACKUP\Android\adt-bundle-windows-x86_64-20140321\sdk\platform-tools; D:\BACKUP\Android\adt-bundle-windows-x86_64-20140321\sdk\; 编辑系统"Path",添加内容: %ANDROID%; 测试ADB命令 启动天天模拟器 运行ADB命令连接模拟器 2 、cd C:\Users\Free\AppData\Local\Android\sdk\platform-tools 3、adb connect 127.0.0.1:6555 参考:http://www.cnblogs.com/yilongm/p/5026021.html 本文转自yunlielai51CTO博客,原文链接:http://blog.51cto.com/4925054/1944675,如需转载请自行联系原作者

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

Android开发学习笔记:反编译APK文件

反编译的目的在于学习一些优秀的Android应用程序代码。 在进行反编译之前,需要准备好下面的软件工具(这些文件都放在同一文件下): 这些工具的下载地址:http://down.51cto.com/data/266751 下面开始进行反编译APK文件: 1.先将上面的apktool-install-windows-2.1_r01-1.zip,dex2jar-0.0.7-SNAPSHOT.zip解压到一个盘的根目录的一个文件下面(这里我选择D:\APKTool) 2.Win+R打开运行界面,输入cmd,进入dos窗口,输入cd /d D:\APKTool进入到D:\APKTool下面,然后输入下面的命令,按Enter键,会出现下图所示 apktool.jar是解包工具,d表示解包,android.apk是要解包的APK文件,红色矩形框表示解包后输出到这个文件夹。这时候打开d:\AndroidCode,就能看到通过解包得到的文件 里面的AndroidManifest.xml文件和res下面的所有文件就能直接打开查看了。 3.解包之后,将之前的android.apk文件的后缀名改为rar,之后就将里面的classes.dex文件解压到D:\APKTool下面。然后在dos窗口输入dex2jar.bat classes.dex 得到一个名为classes.dex.dex2jar.jar的文件,此时用jd-gui.exe打开classes.dex.dex2jar.jar或者用DJ Java Decompiler反编译工具将.class文件反编译成.java文件就能看到所有源代码了! PS:APK文件反编译之后,XML的源码不会出现乱码,不过有些APK文件得到Java源码会出一些乱码(比如在给变量赋值的时候),我现在没有到更好的解决方法,如果大家有的话,可以给我发邮件的。 邮件地址:lingdududu@163.com 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/690370

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

Android开发学习笔记:对话框浅析

对话框式程序运行中弹出的窗口。Android系统中有四种默认的对话框:警告对话框AlertDialog、进度对话框ProgressDialog、日期选择对话框DatePickerDialog以及时间选择对话框TimePickerDialog。除此之外,我们自定义自已的dialog。 一.警告对话框(AlertDialog) Android系统中最常用的对话框是AlertDialog,它是一个提示窗口,需要用户作出选择的。一般会有几个按钮、标题信息、提示信息等。 在程序中创建AlertDialog的步骤: 1.获得AlertDialog的静态内部类Builder对象,由该类来创建对话框,Builder所提供的方法如下: setTitle():给对话框设置title. setIcon():给对话框设置图标。 setMessage():设置对话框的提示信息 setItems():设置对话框要显示的一个list,一般用于要显示几个命令时 setSingleChoiceItems():设置对话框显示一个单选的List setMultiChoiceItems():用来设置对话框显示一系列的复选框。 setPositiveButton():给对话框添加”Yes”按钮。 setNegativeButton():给对话框添加”No”按钮。 2.调用Builder的create( )方法 3.调用AlertDialog的show( )方法显示对话框 下面是一个提示信息对话框的实例: AlertDialogActivity.java package com.android.dialog.activity; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class AlertDialogActivity extends Activity { private TextView tv; private Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView)findViewById(R.id.TextView_1); btn = (Button)findViewById(R.id.Button_1); //实例化AlertDialog.Builder对象 final AlertDialog.Builder builder = new AlertDialog.Builder(this); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { //设置提示信息,确定按钮 builder.setMessage("真的要删除该文件吗?").setPositiveButton("是", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { tv.setText("成功删除"); } //设置取消按钮 }).setNegativeButton("否", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { tv.setText("取消删除"); } }); //创建对话框 AlertDialog ad = builder.create(); //显示对话框 ad.show(); } } ); } } main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns: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/TextView_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试AlertDialog" /> <Button android:id="@+id/Button_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除文件" /> </LinearLayout> 效果图: 二.进度对话框(ProgressDialog) 在程序中创建ProgressDialog的步骤: 1.覆盖Activity的onCreateDialog( )方法,并在其中创建对话框 2.调用Activity的showDialog( )方法,显示进度对话框 下面是一个提示进度对话框的实例: ProgressDialogActivity.java packagecom.android.progress.activity; importandroid.app.Activity; importandroid.app.Dialog; importandroid.app.ProgressDialog; importandroid.content.DialogInterface; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassProgressDialogActivityextendsActivity{ privateButtonbtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btn=(Button)findViewById(R.id.Button_1); btn.setOnClickListener(newOnClickListener(){ publicvoidonClick(Viewv){ //调用Activity的showDialog()方法,显示进度对话框 showDialog(0); } }); } @Override protectedDialogonCreateDialog(intid){ //对进度对话框进行实例化 ProgressDialogdialog=newProgressDialog(this); //设置显示的标题 dialog.setTitle("测试ProgressDialog"); dialog.setIndeterminate(true); dialog.setMessage("程序正在Loading..."); dialog.setCancelable(true); dialog.setButton(Dialog.BUTTON_POSITIVE,"确定", newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.cancel(); } } ); returndialog; } } 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/Button_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试ProgressDialog" /> </LinearLayout> 效果图: 三.日期,时间选择对话框(DatePickerDialog、TimePickerDialog) 在程序中创建日期,时间选择对话框的步骤: 1.覆盖Activity的onCreateDialog( )方法,并在其中创建对话框 2.分别在OnDateSetListener的onDateSet( )方法和OnTimeSetListener( )的onTimeSet( )事件方法中更改日期,时间 3.调用Activity的showDialog( )方法,显示进度对话框 MainActivity.java packagecom.android.datatime.activity; importjava.util.Calendar; importandroid.app.Activity; importandroid.app.DatePickerDialog; importandroid.app.Dialog; importandroid.app.TimePickerDialog; importandroid.app.DatePickerDialog.OnDateSetListener; importandroid.app.TimePickerDialog.OnTimeSetListener; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.DatePicker; importandroid.widget.TextView; importandroid.widget.TimePicker; publicclassMainActivityextendsActivity{ privateButtonbtn1,btn2; privateTextViewtv_1,tv_2; privateCalendarc;//获得日历实例 privateintm_year,m_month,m_day; privateintm_hour,m_minute; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btn1=(Button)findViewById(R.id.Button_1); btn2=(Button)findViewById(R.id.Button_2); c=Calendar.getInstance(); m_year=c.get(Calendar.YEAR); m_month=c.get(Calendar.MONTH); m_day=c.get(Calendar.DAY_OF_MONTH); m_hour=c.get(Calendar.HOUR); m_minute=c.get(Calendar.MINUTE); tv_1=(TextView)findViewById(R.id.TextView_1); tv_1.setText(m_year+":"+(m_month+1)+":"+m_day);//设置TextView里的内容为日期 tv_2=(TextView)findViewById(R.id.TextView_2); tv_2.setText(m_hour+":"+m_minute);//设置TextView里的内容为时间 btn1.setOnClickListener(newOnClickListener(){ publicvoidonClick(Viewv){ showDialog(0);//显示日期对话框 } }); btn2.setOnClickListener(newOnClickListener(){ publicvoidonClick(Viewv){ showDialog(1);//显示时间对话框 } }); } //调用Activity的showDialog()方法显示进对话框 protectedDialogonCreateDialog(intid){ if(id==0) returnnewDatePickerDialog(this,l1,m_year,m_month,m_day); else returnnewTimePickerDialog(this,l2,m_hour,m_minute,false); } //设置日期监听器 privateOnDateSetListenerl1=newOnDateSetListener(){ publicvoidonDateSet(DatePickerview,intyear,intmonthOfYear, intdayOfMonth){ m_year=year; m_month=monthOfYear; m_day=dayOfMonth; tv_1.setText(m_year+":"+(m_month+1)+":"+m_day);//为TextView设置文本内容,重新显示日期 } }; //设置时间监听器 privateOnTimeSetListenerl2=newOnTimeSetListener(){ publicvoidonTimeSet(TimePickerview,inthourOfDay,intminute){ m_hour=hourOfDay; m_minute=minute; tv_2.setText(m_hour+":"+m_minute);//为TextView设置文本内容,重新显示时间 } }; } 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:text="" android:id="@+id/TextView_1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="" android:id="@+id/TextView_2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:text="修改日期" android:id="@+id/Button_1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:text="修改时间" android:id="@+id/Button_2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/641365

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

IOS开发需要知道的知识-RunLoops

什么是Run Loops Run Loops是与线程想关联的基础部分。一个Run Loop就是事件处理循环,它是用来调度和协调接收到的事件处理。使用Run Loop的目的,就是使得线程有工作需要做时可以忙碌起来,而当没有事可做时,又可以使得线程睡眠。 Run Loop管理不都是自动的。我们必须手动设计线程代码,在合适的时候来启动Run Loop,并回应到来的事件。Cocoa和Core Foundation都提供了run loop对象来帮助我们配置和管理线程的run loop。我们的应用没有必要显式地创建这些对象;每个线程,包括应用程序的主线程,都有一个与之关联的run loop。只有子线程才需要显式地运行其run loop。App会将自动配置和来运行主线程的run loop的任务作为应用程序启动处理的一部分。 对于想要更深入地了解Run Loop Objects,阅读NSRunLoop Class Reference、CFRunLoop Reference 一个Run Loop的结构 Run Loop就像它的名字一样,它使得线程进入事件循环,能对到来的事件启动事件处理。你的代码中提供了流程控制说一句来实现run loop实实在在的循环部分,换句话说,你的代码提供了while或者for循环来驱动run loop。在你的循环中,你使用run loop对象在事件到达时,运行事件处理的代码并调起已安装的处理程序。Run Loop接收来自两种不同类型的源(sources)的事件: 输入源:异步传递事件,通常是来自不同的线程或不同的应用的消息。输入源异步传递事件到对应的处理程序和在线程关联的NSRunLoop对象调起runUntilDate:方法来退出事件处理。 Timer源:同步地传递事件,发生在每个定时器调用或周期性地调用。Timer源传递事件到他们的处理程序,但是不会调用run loop来退出处理。 这两种源在事件到达时都使用应用程序特定的处理程序来处理事件。 如下图所示,展示了run loop和不同的源的概述结构。 image 除了处理输入源之外,run loops还发出关于run loop行为的通知。我们可以注册成为run loop的观察者,就可以接收这些通知和使用它在线程上做一些额外处理。我们可以使用Core Foundation在对应的线程上注册成为run loop的观察者。 Run Loop Modes Run Loop模式是一个监视输入源和定时器的集合和注册成为run loop的观察者的集合。每次要运行run loop,都需要显示或隐式地指定某种运行的mode。只有与这种指定的mode关联的源才会被监视和允许传递他们的事件,同样地,只有与这种模式关联的观察者都会收到run loop行为变化的通知。与其它模式想关联的源,直到随后在合适的模式通过循环后,都会接收到新的事件(比如,将timer加入run loop default模式下,当滚动时,timer不会收到回调,直到停止滚动回到default模式下)。 在我们的代码中,我们通过名称来唯一标识mode。在Cocoa和Core Foundation中都定义了default模式和几个常用的模式,都是通过字符串名称来指定。我们也可以自定义模式,但是我们需要手动添加至少一个input source/timers/observers。 我们可以通过使用mode来过滤掉我们不希望接收到来自不想要的通过run loop的源。大部分情况下,我们都是使用系统定义的default模式。对于子线程,我们可以使用自定义模式在关键性操作时阻止低优先级的源传递事件。注意:Modes是通过事件源来区分,而不是事件类型来区分。比如说,我们不能使用mode来匹配只有mouse-down事件或者只有键盘事件。我们可以使用modes来监听不同系统的端口,临时挂起定时器,甚至改变正在被监视的sources和run loop观察者。 表格.png Input Sources 输入源异步传递事件到你的线程。事件的源由输入源的类型来决定,也就是两种源中的其中一种: Port-based:基于端口号的输入源监听应用程序的Mach端口。 Custom Input Sources:自定义输入源监听自定义的事件源。 系统通常实现了这两种输入源。唯一的不同点是它们是如何被发出信号的。port-based源是由内核(kernel)自动发出信号,而custom sources必须手动从其它线程发出信号。 当我们创建输入源时,可以指定mode。Modes会影响任何时刻被监视的输入源。大部分情况下,我们都让run loop在default mode下运行,但是也可以指定自定义的mode。如果一个输入源不是当前所监视的model,它所产生的任何事件都会被保留直接进入正常的mode。 Port-Based Sources Cocoa和Core Foundation提供了内建支持,可以使用与port相关的对象和函数来创建基于端口的输入源。举个例子,在Cocoa中永远不需要手动创建输入源。我们只需要简单地创建一个port对象和使用NSPort的方法。port对象为我们处理所需要的输入源的创建和配置。 在Core Foundation中,我们必须手动创建port和source。在这两种情况下,我们可以使用与port opaque type关联的函数(CFMessagePortRef, or CFSocketRef) 来创建合适的对象。 Custom Input Sources 在Core Foundation中,要创建自定义输入源,我们必须使用与CFRunLoopSourceRef关联的函数。我们配置自定义输入源可以使用几个回调函数。Core Foundation会在不同点回调这些函数来配置source,处理任何到达的事件和销毁已从run loop移除的source。 除了定义在事件到达时自定义源的行为之外,我们也必须定义事件传递机制。这部分源运行在单独的线程,负责提供输入源的数据,当数据准备好可以处理时,signaling(通知相关线程)这个消息。事件传递机制是我们自己来决定,但是不需要过于复杂。 Cocoa Perform Selector Source 除了基于端口的源之外,Cocoa还定义了自定义输入源允许我们在任意线程上执行selector。就像port-based源一样,执行selector请求会在目标线程上序列化,以减少在同一个线程中出现多个方法同步执行的问题。与port-based源不同的是,执行selector源在执行完毕后会自动将自己从run loop中移除。 当执行在其它线程执行selector时,目标线程必须要有运行的run loop。当我们创建线程时,这意味着直到启动了run loop都会显式地执行selector代码。 Run Loop每次经过一个循环,就会处理队列中所有的selector,而不仅仅是处理一个。 方法和说明。 Timer Sources Timer源在未来设定的时间会同步地传递事件到你的线程。Timers是线程通知自己去做一些事情的一种方式。比如说,搜索框可以使用定时器来初始化在一定时间就自动搜索,以便提供更多地联想词给用户。 尽管它发送基于时间的通知,但定时器并不是一种实时的机制。像输入源一样,定时器只有与run loop的mode一样才会发送通知。如果timer在run loop中并不是所被监视的mode,它不会触发定时器,直到run loop的mode与timer所支持的mode一样。 同样地,如果run loop正在处理中,timer已经fire了,这时候会被中断,直到下一次通过run loop才会调志处理程序。如果run loop已经不再运行了,则timer永远不会再fire。 我们可以配置timer只产生事件一次或者重复产生。重复的timer会自动根据调度的firing time自动调度,而不是真实的firing time。比如说,如果一个timer在特定的时间调度,然后每5秒重复一次。如果firing time被延迟导致缺少一或多次调用,那么timer在缺失的周期中只会调用一次。 Run Loop Observers 与sources在适当时机异步或同步发出事件不同,observers在run loop本身执行期间,会在特定的地方发出。你可能需要到run loop observers去准备线程处理特定的事件或者在进入睡眠之前。我们可以通过以下事件来关联run loop observers: 进入runlooprunloop将要处理timer runloop将要处理输入源 runloop将要进入睡眠 runloop被唤醒,但是还没有处理事件 退出runloop 我们可以通过Core Foundation来添加run loop observers。要创建run loop observer,可以通过CFRunLoopObserverRef来创建新的实例。这个类型会跟踪你所定义的回调函数和所感兴趣的活动。 与timers类型,run-loop observers可以使用一次或者重复多次。一次性的observer会在fire之后自动从run loop移除,而重复性的observer会继续持有。 The Run Loop Sequence Of Events 本小节讲的是RunLoop事件顺序。每次运行它,你的线程的run loop处理待处理的事件和给所有attached observers发出通知。处理的顺序如下: 1.通知observersrunloop已经进入2.通知observerstimers准备要fire3.通知observers有不是基于port-based的输入源即将要fire4.fire任何已经准备好的non-port-based输入源5.如果port-based输入源准备好且等待fire,则立即处理这个事件。然后进入步骤96.通知observers线程即将进入睡眠7.让线程进入睡眠,直到以下任何一种事件到达: *port-based输入源有事件到达 *timerfire *runloop超时 *runloop被显式唤醒8.通知observers线程被唤醒9.处理待处理的事件: *如果用户定义的timerfired了,处理timer事件并重新启动循环。进入步骤2 *如果输入源fired了,则传递事件 *如果runloop被显式唤醒,但是又未超时,则重启循环,进入步骤210.通知observersrunloop退出 由于observer对timer和输入源的通知会在事件真正发生之前被传递,这样就产生了间隙。如果这个间隙是很关键的,那么我们可以通过使用sleep和awake-from-sleep通知来帮助我们纠正这个时间间隔问题。 When Would You Use A Run Loop? 什么时候应该使用run loop呢? 只有当我们需要创建子线程的时候,才会需要到显示地运行run loop。应用程序的主线程的run loop是应用启动的基础任务,在启动时就会自动启动run loop。所以我们不需要手动启动主线程的run loop。 对于子线程,我们需要确定线程是否需要run loop,如果需要,则配置它并启动它。我们并不问题需要启动run loop的。比如说,如果我们开一个子线程去执行一些长时间的和预先决定的任务,我们可能不需要启动run loop。Run loop是用于那么需要在线程中有更多地交互的场景。比如说,我们会在下面的任何一种场景中需要开启run loop: 使用端口源或者自定义输入源与其它线程通信 在线程中使用定时器 使用Cocoa中的任何performSelector…方法 保持线程来执行周期性的任务 Using Run Loop Objects Run Loop对象给添加输入源、定时器和观察者到run loop提供了主接口。每个线程都有一个单独的run loop与之关联(对于子线程,若没有调用过任何获取run loop的方法是不会有run loop的,只有调用过,才会创建或者直接使用)。 在Cocoa中,通过NSRunLoop来创建实例,在low-level应用中,可以使用CFRunLoopRef类型,它是指针。 Getting A Run Loop Object 通过以下两种方式来获取run loop对象: 在Cocoa中,使用[NSRunLoop currentRunLoop]获取 使用CFRunLoopGetCurrent()函数获取 配置RunLoop 在子线程运行run loop之前,你必须至少添加一种输入源或者定时器。如果run loop没有任何的源需要监视,它就会立刻退出。 除了添加sources之外,你还可以添加观察者来检测runloop不同的执行状态。要添加观察者,可以使用CFRunLoopObserverRef指针类型和使用CFRunLoopAddObserver函数来添加到run loop中。我们只能通过Core Foundation来创建run loop观察者,即使是Cocoa应用。 下面这段代码展示主线程如何添加观察者到run loop以及如何创建run loop观察者: -(void)threadMain{//应用程序使用垃圾收集,因此不需要autorelease池。 NSRunLoop*myRunLoop=[NSRunLoopcurrentRunLoop];//创建一个运行循环观察者并将它附加到运行循环。 CFRunLoopObserverContextcontext={0,self,NULL,NULL,NULL};CFRunLoopObserverRefobserver=CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities,YES,0,&myRunLoopObserver,&context);if(observer){CFRunLoopRefcfLoop=[myRunLoopgetCFRunLoop];CFRunLoopAddObserver(cfLoop,observer,kCFRunLoopDefaultMode); }//创建和安排计时器。 [NSTimerscheduledTimerWithTimeInterval:0.1target:self selector:@selector(doFireTimer:)userInfo:nilrepeats:YES];NSIntegerloopCount=10;do{//运行运行循环10次让计时器。 [myRunLooprunUntilDate:[NSDatedateWithTimeIntervalSinceNow:1]]; loopCount--; }while(loopCount); } 在为长时间存在的线程配置run-loop时,最好添加至少一个输入源来接收事件。尽管我们可以只用timer源,但是一旦timer调用后,经常会被invalidate,这会导致run loop退出。 Starting the Run Loop 只有子线程才有可能需要启动run loop。Run loop必须至少有一种输入源或者timer源来监视。如果没有任何源,则run loop会退出。 下面的几种方式可以启动run loop: 无条件地:无条件进入run loop是最简单的方式,但也是最不希望这么做的,因为这样会导致run loop会进入永久地循环。可以添加、删除输入源和timer源,但是只能通过kill掉run loop才能停止。而且还不能使用自定义mode。 限时:与无条件运行run loop不同,最好是给run loop添加一个超时时间。 在特定的mode:除了添加超时时间,还可以指定mode。 下面是运行run loop的一段代码: -(void)skeletonThreadMain{//建立一个autorelease如果不使用垃圾收集池。 BOOLdone=NO;//添加你的来源或计时器运行循环,做其他任何设置。 do{//启动运行循环但每个源处理后返回。 SInt32result=CFRunLoopRunInMode(kCFRunLoopDefaultMode,10,YES); //如果源明确停止运行循环,或如果没有源或计时器,然后退出。if((result==kCFRunLoopRunStopped)||(result==kCFRunLoopRunFinished)) done=YES; //检查任何其他退出条件和设置完成所需的变量。}while(!done); //清理代码。一定要释放任何生成自动分配池。 } Exiting the Run Loop 有两种方法使run loop在处理事件之前,退出run loop: 给runloop设定超时时间 告诉runloop要stop 设定超时时间是比较推荐的。我们可以通过CFRunLoopStop函数来停止run loop。 Thread Safety and Run Loop Objects Core Foundation中的Run Loop API是线程安全的(以CF开头的API),而Cocoa中的NSRunLoop不是线程安全的。 Configuring Run Loop Sources 下面是展示如何配置不同类型的输入源。 Defining a Custom Input Source 创建自定义输入源涉及到以下部分: 想要处理的输入源的信息 让感兴趣的客户端知道如何联系输入源的调度程序 执行任何客户端发送的请求处理程序 使输入源失效的取消程序 Timer Source NSRunLoop*myRunLoop=[NSRunLoopcurrentRunLoop]; //创建和安排第一个定时器。NSDate*futureDate=[NSDatedateWithTimeIntervalSinceNow:1.0];NSTimer*myTimer=[[NSTimeralloc]initWithFireDate:futureDate interval:0.1 target:self selector:@selector(myDoFireTimer1:) userInfo:nil[myRunLoopaddTimer:myTimerforMode:NSDefaultRunLoopMode]; 或者使用Core Foundation: CFRunLoopRefrunLoop=CFRunLoopGetCurrent();CFRunLoopTimerContextcontext={0,NULL,NULL,NULL,NULL};CFRunLoopTimerReftimer=CFRunLoopTimerCreate(kCFAllocatorDefault,0.1,0.3,0,0, &myCFTimerCallback,&context);CFRunLoopAddTimer(runLoop,timer,kCFRunLoopCommonModes); 最后 本篇文章主要是官方文档的部分翻译版本,不过有很多无关的都省略了,而且有都转换成笔者的语言来表达出来,如果读不懂,最好还是去看官方文档吧。毕竟,英文与中文翻译不管怎么翻译都存在很大的问题。 疑问 官方文档中提到,每个线程都有一个run loop与之关联。但是实质上子线程在没有访问过run loop时,是不存在的。当访问时,若不存在则创建run loop并放到全局数组中。 本文转自 卓行天下 51CTO博客,原文链接:http://blog.51cto.com/9951038/1766775,如需转载请自行联系原作者

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

离线安装Eclipse的Android ADT开发插件

不知道大家是不是有过这样的感觉。从 https://dl-ssl.google.com/android/eclipse/ 很慢呢!我是教育网所以确实是很慢的。 所以我想了一个办法确保可以快点安装上ADT15。当然ADT16、ADT17也是可以的。不过我还是用ADT15做演示把。 很熟悉把,这是Eclipse解压后的图片当然ADT是要自己下载的。我们51CTO下载哪儿也有好多的,大家自己去下载,我就不提供下载地址啦。 打开Eclipse, 在菜单栏上选择 help->Install New SoftWare 出现如下界面: 点击 Add按钮,出现如下界面 在Name这而随意输入一个名字:ADT15; 点击打开Archives如图: 记得啦ADT一定要是ZIP格式的呢。 打开后如图: 点击“Next”: 再次点击“Next”: 选择“I accept the ......”,就可以点击“Finish”啦: 嘻嘻,Eclipse问你要安装吗。肯定是“OK”: 继续选择“OK” Eclipse问你要重启Eclipse吗?当然要啦,不然怎么使用ADT。还是“OK”: 重启Eclipse后,点击菜单window->preferences,进入如下界面 选择你的android SDK解压后的目录,选错了就会报错,这个是升级工具,目前还没有一个版本的SDK。 就可以安装好啦。 读者可以参考:http://mobile.51cto.com/android-227548.htm 希望我的博文对大家有帮助。有疑问可以留言呢。 本文转自 梦朝思夕 51CTO博客,原文链接:http://blog.51cto.com/qiangmzsx/828182

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

【移动开发】Android应用程序完全退出

前段期间,参加比赛做项目时遇到了一个问题:Android中应用程序弹出退出对话框退出应用程序时,老是出现上一个Activity,于是将在Activity跳转时将其finish()掉,结果还是不行!寻其原因:原来项目中有好多Activity用来显示界面,之间还掺扎着数据信息的交流,我们知道Activity是以栈的方式存放,要想将程序退出,自然得将众多Activity销毁掉了! 后来在网上查阅了一下,找到了解决方法,在此总结一下前辈们知识,使其更加系统化! 1.任务管理器方法(ActivityManager): 首先要说明该方法运行在Android 1.5 API Level为3以上才可以,同时需要权限 1 2 ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE); am.restartPackage(getPackageName()); 系统会将,该包下的 ,所有进程,服务,全部杀掉,就可以杀干净了,要注意加上 1 < uses-permission android:name=\"android.permission.RESTART_PACKAGES\"></ uses-permission > 2.Dalvik VM的本地方法: 1 2 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID System.exit( 0 ); //常规java、c#的标准退出法,返回值为0代表正常退出 3.一种比较流行的Android经典完美退出方法: 使用单例模式创建一个Activity管理对象,该对象中有一个Activity容器(具体实现自己处理,使用LinkedList等)专门负责存储新开启的每一个Activity,并且容易理解、易于操作,非常不错! A.MyApplication类(储存每一个Activity,并实现关闭所有Activity的操作) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class MyApplication extends Application { //对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList实现了基于动态数组的数据结构,要移动数据。LinkedList基于链表的数据结构,便于增加删除 private List<Activity> activityList = new LinkedList<Activity>(); private static MyApplication instance; private MyApplication(){ } //单例模式中获取唯一的MyApplication实例 public static MyApplication getInstance() { if ( null == instance) { instance = new MyApplication(); } return instance; } //添加Activity到容器中 public void addActivity(Activity activity) { activityList.add(activity); } //遍历所有Activity并finish public void exit(){ for (Activity activity:activityList) { activity.finish(); } System.exit( 0 ); } } B.在每一个Activity中的onCreate方法里添加该Activity到MyApplication对象实例容器中 1 MyApplication.getInstance().addActivity( this ); C.在需要结束所有Activity的时候调用exit方法 1 MyApplication.getInstance().exit(); 4.广播方式: A. MyAcitivty类说明:Acitivty的子类,基础该类的子类必须实现onCreate 方法,在该类中注册了一个BroadcastReceiver 用于接收退出消息,在接收到消息之后结束自身 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public abstract class MyAcitivty extends Activity { /**负责各个具体 Activity 的显示**/ public abstract void onCreate(); @Override public void onCreate( final Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); onCreate(); RegListener(); } /**注册退出事件监听**/ public void RegListener() { ExitListenerReceiver exitre = new ExitListenerReceiver(); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction( this .getPackageName() + "." + "ExitListenerReceiver" ); this .registerReceiver(exitre, intentfilter); } class ExitListenerReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent i) { ((Activity) context).finish(); } } } B.自己的Activity都继承MyAcitivty,到需要退出程序的时候发送广播 1 2 Intent intent = new Intent(context.getPackageName()+ ".ExitListenerReceiver" ); context.sendBroadcast(intent); 即可。 5.一个技巧方式: A.首先设定一个公用的class:Setting.java,定义一个静态类成员 1 public boolean static isCloseAll= false ; B.然后,在每一个Activity的onResume()加入这一个: 1 2 3 4 5 @Override onResume() { super .onResume(); if (Setting.isCloseAll) finish(); } C.当最后一个Activity需要结束整个程序便执行: 1 2 Setting.isCloseAll= true ; finish(); 6.捕获空指针异常 A.通过异常并在Application的子类中重新注册Thread的 Thread.UncaughtExceptionHandler接口: 1 2 3 4 5 6 7 8 9 10 package com.example.android_uncatchexception; import android.app.Application; public class MyCrashApplication extends Application { @Override public void onCreate() { super .onCreate(); //程序一启动,就将未捕获异常初始化 CrashHandler.getInstance().init(getApplicationContext()); } } 注:记得注册Application B.自定义异常捕获类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.example.android_uncatchexception; import java.lang.Thread.UncaughtExceptionHandler; import android.content.Context; import android.util.Log; /** * 自定义异常捕获类 * * @author ZHF */ public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler" ; // 程序的Context对象 private Context mContext; /** 单例模式 **/ private CrashHandler() { } /** 懒汉式 **/ private static class CrashHolder { static final CrashHandler crashHandler = new CrashHandler(); } public static CrashHandler getInstance() { return CrashHolder.crashHandler; } public void init(Context context) { mContext = context; // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler( this ); } @Override public void uncaughtException(Thread thread, Throwable ex) { Log.d(TAG, "uncaughtException--->thread" + thread + " name: " + thread.getName() + " id: " + thread.getId() + "exception--->" + ex); String threadName = thread.getName(); if ( "main" .equals(threadName)) { Log.d(TAG, "在主线程的崩溃!" ); } else { //这里我们根据thread name来进行区别对待:可以将异常信息写入文件供以后分析 Log.d(TAG, "在子线程中崩溃!" ); } android.os.Process.killProcess(android.os.Process.myPid()); //杀死该进程 System.exit( 0 ); //退出 } } C.在要退出的地方制造空指针异常即可实现闪退,并且不会弹出ANR对话框 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.example.android_uncatchexception; import android.os.Bundle; import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { Button mBtn; String str; //不要初始化,为了下面制造空指针异常 @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBtn = (Button) this .findViewById(R.id.button1); mBtn.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { //NullPointerException System.out.println(str); } }); } } 7.网上还有一些其他方式: A.restartPackage、 B. killBackgroundProcesses 不常用,大家可以自行参考哦~ 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1248643,如需转载请自行联系原作者

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

Android开发中ANR问题出现及解决

写在前面:Application Not Responding。在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择“等待”而让程序继续运行,也可以选择“强制关闭”。所以一个流畅的合理的应用程序中不能出现anr,而让用户每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样系统不会显示ANR给用户。默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒。 第一:什么会引发ANR? 在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR: 1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸) 2.BroadcastReceiver在10秒内没有执行完毕 造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。 第二:如何避免ANR? 1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等) 2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子 线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍,此处不是本文重点) 3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。 总结:anr异常也是在程序中自己经常遇到的问题,主要的解决办法自己最常用的就是不要在主线程中做耗时的操作,而应放在子线程中来实现,比如采用Handler+mesage的方式,或者是有时候需要做一些和网络相互交互的耗时操作就采用asyntask异步任务的方式(它的底层其实Handler+mesage有所区别的是它是线程池)等,在主线程中更新UI。 本文转自 小强测试帮 51CTO博客,原文链接:http://blog.51cto.com/xqtesting/1438553,如需转载请自行联系原作者

资源下载

更多资源
Nacos

Nacos

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

Spring

Spring

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

Rocky Linux

Rocky Linux

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

WebStorm

WebStorm

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

用户登录
用户注册