├── ActionBarNavigation ├── Prerequisites.md └── README.md ├── ActionModes └── README.md ├── ActivitiesandTheirLifecycles ├── ApplicationTranscedingtheActivity.md ├── AsynchronicityandResults.md ├── CreatingYourSecondActivity.md ├── Life,Death,andYourActivity.md ├── PonderingParcelable.md ├── README.md ├── RecyclingActivities.md ├── Schroedinger'sActivity.md ├── TheCaseoftheInvisibleActivity.md ├── UsingImplictIntent.md ├── WalkingThroughtheLifecycle.md ├── Warning!ContainsExplictIntents.md ├── WhenActivitiesDie.md └── extra!extra!.md ├── AdapterViewsAndAdapters └── README.md ├── AdvancedListViews └── README.md ├── AndroidandProjects ├── CommonConcepts.md ├── ProjectandAndroidStudio.md ├── README.md └── StarterProjectGenerators.md ├── AudioPlayback ├── GetYourMediaOn.md ├── MediaPlayerForAudio.md ├── OtherWaysToMakeNoise.md ├── Prerequisites.md └── README.md ├── AudioRecording ├── Prerequisites.md ├── README.md ├── RawAudioInput.md ├── RecordingbyIntent.md ├── RecordingtoFiles.md ├── RecordingtoStreams.md └── RequestingtheMicrophone.md ├── BasicWidgets ├── ACommandingButton.md ├── AssigningLables.md ├── CommonConcepts.md ├── FOGFOOC.md ├── FleetingImages.md ├── MoreCommonConcepts.md ├── README.md └── VisittheTrails.md ├── ChoosingYourDevelopmentToolchain ├── C-LBuildviaGradleforAndroid.md ├── IDEs...AndThisBook.md ├── README.md ├── WhatWeAreNotCovering.md ├── YetOtherAlternatives.md ├── androidstudio.md ├── eclipse.md └── intelli_idea.md ├── ContentsofAndroidProjects ├── ProjectsandthisBook.md ├── README.md ├── TheContentsofanAndroidStudioProject.md ├── TheContentsofanEclipseProject.md ├── WhatYouGet,InGeneral.md └── WhatYouGetOutOfIt.md ├── CustomDrawables ├── Prerequisites.md └── README.md ├── DealingWithThreads ├── AlternativestoAsyncTask.md ├── AndNow,TheCaveats.md ├── AsyncingFeeling.md ├── EventBuses.md ├── GettingtotheBackground.md ├── README.md ├── TheMainApplicationThread.md └── VisittheTrails!.md ├── EventBusAlternatives └── README.md ├── FindingandEliminatingJank └── README.md ├── FoucusOnNDK ├── Prerequisites.md ├── README.md └── TheRoleoftheNDK.md ├── GettingAroundAndroidStudio ├── AccessingAndroidTools.md ├── AndroidStudioandReleaseChannels.md ├── NavigatingTheProjectExplorer.md ├── README.md ├── RunningProjects.md ├── ViewingOutput.md └── VisittheTrails.md ├── GradleandDependencies ├── APropertyofTransitive.md ├── APropertyofTransitiveDependencies.md ├── ATaleofTwoDenpendenciesClosures.md ├── CreatingAndroidJARsfromGradle.md ├── DenpendingUponanAndroidLibraryProject.md ├── Dependencies.md ├── DependenciesByBuildType.md ├── DependenciesByFlavor.md ├── DependenciesandtheProjectStructureDialog.md ├── DependingUponArtifacts.md ├── DependingUponNDKBinaries.md ├── DependingUponSubProjects.md ├── DependingUponaJAR.md ├── ExaminingSomeCWACBuilds.md ├── PrerequisitesandWarning.md └── README.md ├── GradleandEclipseProject ├── CreatingYourGradleBuildFile.md ├── ExaminingtheGradleFile.md ├── Legacy.md ├── PrerequisitesandWarnings.md └── README.md ├── GradleandTasks ├── KeyBuild-RelatedTasks.md ├── README.md └── Results.md ├── GradleandtheNewProjectStructure ├── AddingBuildTypes.md ├── AddingProductFlavorsandGettingBuildVariants.md ├── ConfiguringtheStocksBuildTypes.md ├── CreatingaProjectintheNewStructure.md ├── DoingtheSplits.md ├── Falvors,Build,andtheProjectStructureDialog.md ├── ObjectivesoftheNewProjectStructure.md ├── PrerequisitesandWarnings.md ├── README.md ├── RevisitingtheLegacyGradleFile.md ├── Terminology.md ├── WhattheNewProjectStructureLooksLike.md └── WokingwiththeNewProjectStructureinAndroidStudio.md ├── InternetAccess ├── DIYHTTP.md ├── HTTPviaDownloadManager.md ├── README.md ├── SSL.md ├── UsingHTTPClientLibraries.md ├── UsingThird-PartyJARs.md ├── VisittheTrails.md └── WhatAboutHttpClient?.md ├── IntroducingGradleandTheManifest ├── ExaminingtheGradleFiles.md ├── GradleEnvironmentVariables.md ├── GradleTheBigQuestions.md ├── IntroducingtheManifest.md ├── LearningMoreAboutGradlle.md ├── ObtainingGradle.md ├── OtherGradleItemsofNote.md ├── README.md ├── TheRestOftheManifest.md ├── ThingsInCommonBetweenTheManifestandGradle.md ├── VersionsofGradleandGradleforAndroid.md ├── VisittheTrails.md └── Where'sTheGUI.md ├── JUnitandAndroid └── README.md ├── KeyAndroidConcepts ├── AndroidApplications.md ├── AndroidDevices.md ├── Don'tBeScared.md └── README.md ├── MiscellaneousNetworkCapabilities ├── DownloadingFiles.md ├── Prerequisites.md └── README.md ├── Preface ├── AbouttheAPKEdition.md ├── AbouttheUpdates.md ├── Acknowledgment.md ├── CC&42FG.md ├── ExendingYourWarescription.md ├── README.md ├── SourceCodeandItsLicense.md ├── TheBook'sStructure.md ├── TheTrails.md ├── Warescription.md ├── WelcometotheBook.md └── WhatsNewInVersion7.3.md ├── README.md ├── RecyclerView ├── ATrivialList.md ├── AdapterViewanditsDiscontents.md ├── ChangingtheContents.md ├── DividerOptions.md ├── EnterRecyclerView.md ├── Grids.md ├── HandlingClickEvents.md ├── MutableRowContents.md ├── OtherBitsofGoodness.md ├── Prerequisites.md ├── README.md ├── TheMarchoftheLibraries.md ├── TheOrderofThings.md ├── VaryingtheItems.md └── WhatAboutCursors.md ├── RequestingPermissions └── README.md ├── ResourceSetsandConfigurations ├── API-VersionedResources.md ├── AndNow,aWordFromtheAndroidProjectView.md ├── BlockingRotations.md ├── ChoosingTheRightResource.md ├── ConfigurationsandResourceSets.md ├── CopingwithComplexity.md ├── DefaultChangeBehavior.md ├── README.md ├── ScreenSizeandOrientation.md ├── StateSavingScenarios.md ├── What'saConfigurationAndHowDoTheyChange.md └── YourOptionsforConfigurationChanges.md ├── ServicesandtheCommandPattern └── README.md ├── SomeWordsAboutResource ├── Dimensions.md ├── GotthePicture.md ├── README.md ├── StringTheory.md └── TRTSNBNY.md ├── Summary.md ├── SwipingwithViewPager ├── Indicators.md ├── PagingFragments.md ├── PagingOtherStuff.md ├── PiecesofaPager.md ├── README.md └── SwipingDesignPattern.md ├── TheActionBar ├── ActionBarsLiveinLivingColor.md ├── ApplyingtheResource.md ├── BarHopping.md ├── DefiningtheResource.md ├── MENUKey,WeHardlyKnewYe.md ├── README.md ├── RespondingtoEvent.md ├── SettingtheTarget.md ├── TheRestoftheSampleActivity.md ├── VisittheTrails.md ├── YetAnotherHistoryLesson.md └── YourActionBarOptions.md ├── TheAndroidUserInterface ├── DissectingtheActivity.md ├── TheActivity.md └── UsingXML-BasedLayouts.md ├── TheDataBindingFramework ├── ObservablesandUpdatingtheBinding.md ├── OtherFeaturesofNote.md ├── Prerequisites.md ├── README.md ├── TheBasicSteps.md ├── TheBindingExpressionLanguage.md ├── TheExtendedLayoutResource.md └── TheWhatNow.md ├── TheLoaderFramework └── README.md ├── TheMediaStoreProvider └── README.md ├── TheTacticsofFragments ├── FragmentsWithinFragments.md ├── FragmentsandMultipleActivity.md ├── FragmentsandtheActionBar.md ├── README.md ├── TheFragmentLifecycleMethod.md ├── TheSixQuestions.md ├── WhereYouGetYourFragmentFrom.md ├── YourFirstDynamicFragment.md └── YourFirstFragment.md ├── TheTheoryofWidgets ├── README.md ├── Size,Margins,andPadding.md ├── TheAbsolutePositioningAnti-Pattern.md ├── TheThemeofThisSectionThemes.md ├── WhatAreContainers?.md └── WhatAreWidgets?.md ├── TheWebViewWidget └── README.md ├── Tutorial#1-InstallingtheTools ├── InOurNextEpisode.md ├── README.md ├── Step#1-CheckingYourHardwareRequirements.md ├── Step#2-SettingUpJavaand32-BitLinuxSupport.md ├── Step#3-InstalltheDeveloperTools.md └── Step#4-IntalltheSDKsandAdd-Ons.md ├── Tutorial#2-CreatingaStubProject ├── AboutOurTools.md ├── AboutOurTutorialProject.md ├── AbouttheRestoftheTutorials.md ├── InOurNextEpisode.md ├── README.md ├── Step#1CreatingtheProject.md ├── Step#2SetUptheEmulator.md ├── Step#3SetUptheDevice.md └── Step#4RunningtheProject.md ├── Tutorial#3-ChangingOurManifest ├── InOurNextEpisode.md ├── README.md ├── SomeNotesAboutRealtivePaths.md ├── Step#1SupportingScreens.md └── Step#2AddingOurMinimumandTargetSDKVersions.md ├── Tutorial#4-AdjustingOurResources ├── InOurNextEpisode.md ├── README.md ├── Step#1ChangingtheName ├── Step#2ChangingtheIcon └── Step#3RunningtheResult ├── UsingPreferences └── README.md ├── WorkingwithLibraryProjects ├── CreatingaLibraryProject.md ├── LibraryProjectsandtheManifest.md ├── LimitationsofLibraryProjects.md ├── Prerequisites.md ├── README.md └── UsingaLibraryProject,PartII.md └── WritingandUseParcelables └── README.md /ActionBarNavigation/Prerequisites.md: -------------------------------------------------------------------------------- 1 | ###准备工作 2 | 3 | 理解这章需要你已经读过了核心章回,特别是动作栏那一章。 4 | 5 | -------------------------------------------------------------------------------- /ActionBarNavigation/README.md: -------------------------------------------------------------------------------- 1 | ###动作栏导航 2 | 3 | 除了应用图标(又称左侧的图标),动作栏工具项,和溢出菜单之外,动作栏也支持一个导航区域。 4 | 这存在在应用图标的右侧以及工具栏项/溢出菜单的左侧。你可以: 5 | 6 | * 把标签放在这里,允许用户在你应用不同部分之间切换 7 | * 使用"列表导航",这会在这产生一个Spinner,同样也允许用户从一个地方切换到另一个地方 8 | * 放入其他自定义形式的导航,例如搜索区域 9 | 10 | 这章会分析如何使用这些东西,以及它们是如何和Android中的其它结构绑定起来的,特别是ViewPager。 11 | 12 | 注意:这章列出的标签和列表导航形式在Android 5.0中已经被标为废弃了。开发者被推荐使用其它技术来用于活动导航。 13 | 14 | -------------------------------------------------------------------------------- /ActionModes/README.md: -------------------------------------------------------------------------------- 1 | ## Action Modes 2 | 3 | 如果你在Android 3.0+设备上已经花费了大量的时间,你可能已经遇到了一个渴望知道的现象。 4 | 有时候,当你选择列表中一个项或者其它控件时,aciton bar魔术般地从它的常态转化成一个可以对你选择的 5 | 东西进行操作的样子: 6 | 7 | 好消息是这不是内置进Edittext的魔法。你可以通过“action mode",同样也可以让你的应用有这个 8 | 效果。 9 | 10 | 在本章中,我们会探索如何设置并响应action modes。 11 | 12 | 13 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/ApplicationTranscedingtheActivity.md: -------------------------------------------------------------------------------- 1 | ###应用:不只是Activity 2 | 3 | Activity是从一个名叫Context的的类继承而来的。许多我们在我们activity上调用的方法,像startActivity()就是从Context继承而来的。 4 | 5 | 但是,activity不是Context唯一相关的子类。例如,之后我们会看到Service。并且有时候我们会看到空白的Context对象,例如在我们在之后涵盖到BroadcastReveicer的时候。 6 | 7 | 另一个需要注意的Context是Application。当应用被启动的时候一个Application的实例被创建了。Application实例是一个天然单例,在我们的进程中应该确切只有一个Application实例。 8 | 9 | 通常来说,这个单例是Application本身的实例。但是,如果我们想的话我们可以子类化Application,然后包含一个我们的自定义application类到manifest上元素的android:name属性上。然后,当Android启动我们的应用的时候, 10 | 它会创建一个我们所指派的Application子类,而不再是创建一个普通的Application实例。 11 | 12 | 在任意Context对象上调用getApplicationContext()的时候,我们都能够取得Application对象。getApplication() 13 | 会返回一个Context;如果我们需要引用我们所指定的Application子类,我们就需要向下转型返回的Context到合适的类型。 14 | 15 | 在Android应用中,我们有一些能够使用Application的方法。 16 | 17 | 第一点,如果我们需要在一个静态数据成员中持有一些其它对象,并且另外的对象是需要一个Context的话,我们就想要它使用Application,而不是Acticity,Service等。因为Application是一个单例,它实际上是“预先泄露的”。我们不能以某种方式让另一个非直接的静态变量应用它从而造成进一步的泄露。相比之下,假定我们有一个保存在activity的静态数据成员。现在,当Activity被摧毁的时候,它(和所有它持有的,像控件和监听器)不能垃圾回收。这就代表了内存泄露。 18 | 19 | 你可以进一步让Application管理这个静态数据,而不是使用多个独立的单例。这个方法既有优点又有缺点,但是总体来说,Google对这个方法并不感冒。话虽如此,在Application被实例haunted之后onCreate()很快就被调用了,并且你的Application子类可以重载这个方法并使用它来初始化一些全局变量。 20 | 21 | 但是,尽管Java文档指出Application上有一个表明当应用离开并且我们的进程被终止了onTerminate()方法,但是实际上这个方法从没有被调用过。 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/AsynchronicityandResults.md: -------------------------------------------------------------------------------- 1 | ###同步和结果 2 | 3 | 注意,startActivity()是同步的。在你的返回应用主线程控制权给Android之后,另一个activity才会显示出来。 4 | 5 | 通常来说,这不是很大的问题。但是,有些时候一个activity可能启动了另一个,其中第一个activity想知道一些来自 6 | 第二个activity的结果。例如,第二个activity可能是某种选择,允许用户选择一个文件或一个联系人或一首歌或这个其他的, 7 | 并且第一个activity需要知道用户选择了什么。使用同步的startActivity(),我们明显是不可能从startActivity()本身获取某种类型的返回结果。 8 | 9 | 为了处理这个情形,还有一个单独的startActivityForResult()方法。虽然它依然是同步的,它允许新启动的activity提供一个结果(通过一个setResult()方法),这个结果通过onActivityResult()方法传送到了最初的activity。我们会在之后一章中更为详细地分析startActivityForResult()。 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/Life,Death,andYourActivity.md: -------------------------------------------------------------------------------- 1 | ###你的Activity的生死 2 | 3 | 当activity在如上四个状态之间切换的时候,Android会在你的activity中进行回调。 4 | 5 | 注意对于所有这些,你应该向上链接并调用父类的这个方法的版本,或者Android会抛出一个异常。 6 | 7 | 8 | ####onCreate()和onDestory() 9 | 10 | 我们已经在我们所有的例子中的Activity子类中实现了onCreate()方法。这个方法会在以下两个主要情形中 11 | 被带调用: 12 | 13 | * 当activity首次被启动(例如,由于系统重启),onCreate()被调用的时候会传入null参数。 14 | * 如果activity已经处于运行状态了并且你的activity设置成基于不同的设备状态会有不同的资源(例如, 15 | 水平对竖直),你的activity会被重新创建并且onCreate()会被调用。我们会在这本书稍后内容更加详细地 16 | 讨论。 17 | 18 | 不管activity如何被使用,这里是你初始化你的用户界面并设置所有需要立即完成的事情的地方。 19 | 20 | 在生命周期的另一端,当activity被关闭的时候onDestroy()可能会被调用,比如因为activity调用了 21 | finish()方法(这个方法会结束activity)或者用户按下了返回键。因此,onDestory()方法是用阿里清理和释放 22 | 你从onCreate()方法中获取的资源,此外要确保所有你在生命周期方法之外启动的东西被中断了,例如后台线程。 23 | 24 | 记住,尽管如此,onDestory()方法可能不被调用。这可能在一些情形下发生: 25 | 26 | * 你的应用因没有处理的异常崩溃了 27 | * 用户强制中断了你的应用,例如通过设置应用。 28 | * Android有着释放内存的迫切需求(例如,处理一个打进来的电话),想要中止你的进程,并且没有时间去调用所有的 29 | 生命周期方法。 30 | 31 | 因此,onDestory()很有可能被调用,但是不能保证的。 32 | 33 | 34 | 此外,记住onDestory()的调用可能花费一段很长的时间。如果用户按下返回按钮来结束前台activity,onDestory()很快就会调用。但是如果,用户按下HOME按钮来到了主界面,你的activity不会直接被摧毁。直到Android决定优雅地结束你的进程的时候,onDestory()才会被调用。并且这个时间可能是几秒钟,几分钟,甚至几个小时。 35 | 36 | ####onStart(),onRestart(),和onStop() 37 | 38 | 一个activity能够来到前台,要么是因为它是首次被启动的,或者是因为它被遮盖之后被带回到了前台( 39 | 例如,被另一个activity,被一个打进来的电话)。 40 | 41 | onStart()方法会在如上两种情形中被调用。onRestart()方法会在activity已经被中断然后重新启动的时候 42 | 被调用。 43 | 44 | 反过来说,onStop()在activity将要中断的时候被调用。它同样可能没有被调用,和onDestory()没有被调用的原因一样。 45 | 但是,onStop()通常在activity不可见之后相当快的时间内就被调用了,所以onStop()被调用的可能性比onDestory()还要高。 46 | 47 | 48 | ####onPause()和onResume() 49 | 50 | onResume()方法在你的activity来到前台之前被调用,要么在初始化启动之后,要么是从终止状态 51 | 重新启动,要么在来电被清空之后。这是在你的activity上,刷新UI的一个绝佳地方。例如,你正在从一个服务拉取 52 | 一些改变信息(例如订阅的新条目),onResume()同样是一个刷新当前视图的很好的时机,如果适用的话,启动一个后台线程 53 | 去更新视图(例如,通过一个Handler)。 54 | 55 | 反过来说,所有接管用户输入的-大部分是在另一个activity的驱动下-会导致你的onPause()被调用。在这里, 56 | 你应该撤销所有你在onResume()中所做的事情,例如终止后台线程,释放所有你获取的独占资源(例如,相机),和诸如此类的。 57 | 58 | 一旦onPause()被调用之后,Android具有了在任意时间杀死你的activity的进程的权利。因此,你应该不能指望接收 59 | 更多的事件。 60 | 61 | 那么,所以onPause()和onStop()直接的区别是什么呢?如果一个activity来到前台并充满了屏幕, 62 | 你当前的前台activity的onPause()和onStop()会被调用。但是如果,一个activity来到前台但是没有充满 63 | 屏幕,只有你当前的前台activity的onPause()会调用,因为它仍然是可见的。 64 | 65 | ####凑成对 66 | 67 | 如果你在onCreate()中初始化了某些东西,在onDestory()中把它清理掉。 68 | 69 | 如果你在onStart()中初始化了某些东西,在onStop()中把它清理掉。 70 | 71 | 如果你在onResume()中初始化了某些东西,在onPause()中把它清理掉。 72 | 73 | 换句话说,凑成对。例如,不要在onStart()中初始化了某些东西然后尝试在onPause()中进行清理,很多情形下onPause()可能被一系列地多次调用(例如,用户可能启动一个非全屏的activity,这会触发onPause()但没有触发onStop()和onStart())。 74 | 75 | 你要根据你的需要选择生命周期对方法。你可能决定你需要两对(例如,onCreate()/onDestory()和onResume()/onPause()).只要别搞混它们之间对应关系。 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/PonderingParcelable.md: -------------------------------------------------------------------------------- 1 | ###考虑Parcelable 2 | 3 | 就像以上提及到的,`Intent extras`不能处理任意的对象的。这是因为,大都时候,`Intent extras`是跨进程传递的。 4 | 即使你调用startActivity()来启动你自己的多个activity中的一个,请求从你的进程传递到核心系统进程然后在返回到 5 | 你的进程。同时`Intent extras`也传了过去。 6 | 7 | 8 | 因此,`Intent extras`需要是能够转换成一个二进制数组的东西,作为进程间通信的一部分处理传入的Intent对象。你也会看到在其他风格的Android IPC看到这个,例如远程服务。 9 | 10 | 但是,有两种方式你可以尝试,使你的对象以`Intent extras`的形式工作。 11 | 12 | 一种方式是在你的类上实现`Serializable`。这是经典的Java结构,设计成允许你的类的实例和你的实例所持有的序列化的对象,序列化到文件中然后之后从文件中读取出来。 13 | 14 | 15 | 另一种方式是在你的类上实现`Parcelable`。这是一种Android结构,这个结构和`Serializable`非常相似。但是,`Serializable`是为对象的持久化存储而设计的,可能几个月或者几年之后都可以从文件中读取回来。同样的,`Serializable`需要处理java代码上实现这些类的改变,并且同样也需要有着帮助转换旧的,保存过的对象到新的对象上的钩子。这就增加了开销。`Parcelable`只关心把对象转成二进制数据然后进行跨进程传递。它能够做出这个类定义在从对象转换成二进制和二级制转换回对象的过程中不会改变的简单化假定。作为结果,`Parcelable`在Android的跨进程使用方面比`Serializable`快。 16 | 17 | 如果你想要的话,你是欢迎在你自己的类上实现`Parcelable`的。除此之外,所有你在Adnroid Java文档中看到实现了`Parcelable`的类都能放进`Intent extras`中。所以,例如,Uri实现了`Parcelable`,那么你就能把Uri放进 18 | `Intent extras`。不是Android SDK的所有东西都是`Parcelable`的,但是一些像Uri的关键是`Parcelable`的。 19 | 20 | 21 | 更多`Parcelable`的细节,包括你如何在你的类上实现它,会在这本书之后内容出现。 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/README.md: -------------------------------------------------------------------------------- 1 | ##Activity们和它们的生命周期 2 | 3 | 一个Android应用会有多个互无关联的UI界面。例如,一个日历应用需要让用户浏览日历, 4 | 浏览单个事件的详情,编辑一个事件(包括添加一个新的),等等。并且在较小屏设备上,像大部分的 5 | 手机,你可能没有空间把所有这些一次性地挤在屏幕中。 6 | 7 | 为了解决这个问题,你可以有多个activity。你的日历应用可能有一个展示日历的activity,一个用作 8 | 添加或编辑时间,一个用作提供日历如何工作的设置,一个用作网上求助,等等。这些activity中的一些可能是你应用私有的, 9 | 但同时其它的可能被第三方启动,比如你的启动activity主屏幕上是可用的。 10 | 11 | 所有这些表明了你的多个activity中的其中一个有着启动其它activity的方法。例如,如果某人从查看日历的activity点击了一个事件,你可能想要为这个事件展示查看事件的activity。这就意味着,你需要以某种方式能够使查看事件的activity启动并且展示某一特定的事件(用户点击的那一个)。 12 | 13 | 这可以进一步分解成两种情形: 14 | 15 | * 你知道你所要启动的activity,可能是因为它是你应用中的另一个activity。 16 | * 你有着某个东西的引用(例如,一个网页),并且你想要你的用户能用它做些什么,但是你不知道有什么可选的操作。 17 | 18 | 这两种情形在这章中都会涵盖到。 19 | 20 | 此外,时常对你来说知道什么时候activity来到和离开前台是很重要的,因为这样你就可以自动保存或刷新数据,等等。这就是所谓的“activity生命周期”,并且我们也会在这章中详细分析它。 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/RecyclingActivities.md: -------------------------------------------------------------------------------- 1 | ###回收activity们 2 | 3 | 让我们假定我们有三个activity,分别叫做A,B和C.A基于一些用户输入启动了一个B的实例,并且稍后B通过一些更多的 4 | 用户操作启动了C的一个实例。 5 | 6 | 我们的“activity栈”现在是A-B-C,意味着如果我们从C按下返回键,我们就返回到了B,并且如果我们从 7 | B按下了返回键,我们返回到了A。 8 | 9 | 现在,让我们假定我们想从C导航回到A。例如,可能用户按下我们动作栏左侧的图标,我们想要返回到主界面activity,在我们的情形中就是A。如果C调用了startActivity(),指定了A,我们就以A-B-C-A这个activity栈告终了。 10 | 11 | 那是因为启动一个activity时,默认会创建一个新的这个activity的实例。那么,现在我们就有了两份独立的A拷贝。 12 | 13 | 有时候,这是所期望的行为。例如,我们可能有单个ListActivit通过层次数据集向下钻取数据,就像一个目录树。我们可能 14 | 选择保持启动同一个ListAcivity,但是带有不同的`extras`,来展示每一个层级。在这种情形中,我们会想要activity的独立实例,那样返回按钮就表现的就和用户所预期的一样。 15 | 16 | 但是,当我们导航回主界面activity,我们可能不会想要一个单独的A实例。 17 | 18 | 如何解决这个问题和导航到A之后的activity栈的样子有一点关系。 19 | 20 | 如果你想要的activity栈是B-C-A-那么已存在的A拷贝被带到了前台,但是B和C的实例就被留下了-然后你可以在使用 21 | startActicity()的时候添加FLAG_ACTIVITY_FEORDER_TO_FRONT到你的Intent。 22 | 23 | Intent i=new Intent(this,HomeActivity.class); 24 | i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 25 | startActivity(i); 26 | 27 | 取而代之的,如果你想要的activity站仅仅是A-那么如果用户按下了返回键,他们就离开了你的应用-那么你会添加两个 28 | 标记:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP: 29 | 30 | Intent i=new Intent(this,HomeActivity.class); 31 | i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT|Intent.FLAG_ACTIVITY_SINGLE_TOP); 32 | startActivity(i); 33 | 34 | 这会结束栈中位于当前activity和你所启动的activity之前的activity,在我们的情形中,结束了C和B。 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/Schroedinger'sActivity.md: -------------------------------------------------------------------------------- 1 | ###薛定谔的Activity 2 | 3 | 一个activity,通常来说,在任何时间点会处于以下四种状态中的一种: 4 | 5 | 1.Active: activity被用户启动了,正在运行,并且处于前台。这是你用来思考你activity的操作的时候。 6 | 7 | 2.Paused: activity被用户启动了,正在运行,并且是可见的,但另外有个activity覆盖了部分屏幕。 8 | 在这个期间,用户可以看见你的activity但是可能不能和它进行交互。这是一个相对不常见的状态,因为大都数activity 9 | 是被设置成全屏的,没有一个让它们看起来像某种对话框的主题。 10 | 11 | 3.Stopped:activity被用户启动了,正在运行,但是它被其他启动的或切换到的activity挡住了。 12 | 13 | 4.Dead:活动被杀死了,可能是因为用户按下了返回按钮。 14 | 15 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/TheCaseoftheInvisibleActivity.md: -------------------------------------------------------------------------------- 1 | ###不可见Activity的情形 2 | 3 | 有时候,你会要一个没有UI的activity。 4 | 5 | 这是相当少见见的。大部分时候,它会是需要你有一个activity,但是没有真正要以传统的activity样式UI展示给用户的。 6 | 7 | 例如,主界面启动按钮只启动activity。但是,你可能你需要一个主界面启动器仅仅触发一些在后台完成的工作,可能会使用 8 | 一个service(就像这本书稍后内容会讨论的)。 9 | 10 | 你有两种设置不可见activity的方式,包括在元素上使用一个特定的android:theme值。 11 | 12 | 最高效的选择是使用Theme.NoDisplay。有了这个值,就设置UI而言就没有做任何工作。但是,关键限制是所有的工作 13 | 需要在onCreate()方法中完成,并且在那里你需要调用finish()去触发让activity被摧毁。多数情况下,这就能很好地工作。 14 | 15 | 有时候,你需要一个不可见的activity挂起几秒钟,可能是在他被摧毁之前,等待一些回调结果。使用Theme.NoDisplay仍然能够工作...但是只是在较老的Android设备上。在Android 6.0以及更高的版本上,使用Theme.Nodisplay而没有在onCreate()中调用finish()(或者,技术上来说,在onResume()之前)会使你的应用崩溃。 16 | 17 | 变通方案是使用Theme.Translucent.NoTitleBar。这个实际上分配了一个UI给你,但是把它设置成了一个透明的背景并且没有动作栏。用户可能感知到activity在那里-例如,它出现在概览屏上(又名最近任务列表)。也因为activity真的在那,用户可能不能和它所看到的进行交互,例如在底层的主屏幕上。但是,如果activity本身能很快地finish()自己,并且是和用户实时交互的(例如,展示展示一些系统对话框),你可能能够使用这个方法。 18 | -------------------------------------------------------------------------------- /ActivitiesandTheirLifecycles/UsingImplictIntent.md: -------------------------------------------------------------------------------- 1 | ###使用隐式意图 2 | 3 | 显式Intent方式在启动你自己的activity的时候是很好工作的。 4 | 5 | 但是,你可能会启动来自操作系统或第三方应用的activity。在这些情形中,在你的项目中你没有代表其它activity的Java类,那么你就不能使用以类作为参数意图构造器。 6 | 7 | 取而代之的,你会使用"隐式"意图结构,它看起来就像网页的工作方式一样令人讨厌。 8 | 9 | 如果你做过任何Web应用的工作的话,你会意识到HTTP是基于附加到URI的动词的: 10 | 11 | * 我们想要GET这张图片 12 | * 我们想要POST这个脚本到控制器 13 | * 我们想要PUT这个倒REST资源 14 | * 等等 15 | 16 | Android的隐式意图模式差不多是相同的方式,只不过有更多的动词。 17 | 18 | 19 | 例如,你从某个地方获取了经纬度(例如,微博的内容,短信消息的内容)。你决定你要在地图上展示这些坐标。你有很多方式可以直接嵌入Google地图到你的应用,并且会在之后的章回看到底怎么做-但是展示复杂的并且是以用户想要使用Google地图为前提的。如果我们可以创建通用类型的请求,“你好,Android,展示一个显示这个坐标到地图上的activity”。 20 | 21 | 或者,在一个更为简单的情形中,我们获取到了来自某个来源的网页URL(例如,Web服务调用)并且我们想要在这页上代开一个浏览器。这会在Actities/LauncheWeb样例项目中进行举例说明。 22 | 23 | 其中,我们有一个使用了一个包含一个EditText控件和Button的布局的LauchDemo Activity。 24 | 25 | 26 | 27 | 31 | 32 | 38 | 39 |