LeoYan Blog

技术分享,生活记录。

0%

转载请注明出处:www.leoyanblog.com

本文出自 LeoYan 的博客

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 LeoYan 即可关注。

Activity的生命周期

Activity的形态

Active/Running:

  Activity处于活动状态,此 Activity 位于屏幕前台并具有用户焦点。此时Activity处于栈顶,是可见状态,可与用户进行交互。

Paused:

  另一个 Activity 位于屏幕前台并具有用户焦点,但此 Activity 仍可见。也就是说,当ActivityA失去焦点时,或被一个新的非全屏的ActivityB,或被一个透明的ActivityB放置在栈顶时,ActivityA就转化为Paused状态。但我们需要明白,此时ActivityA只是失去了与用户交互的能力,其所有的状态信息及其成员变量都还存在,只有在系统内存极度不足的情况下,可能会被系统终止。

Stopped:

  当一个Activity被另一个Activity完全覆盖时,被覆盖的Activity就会进入Stopped状态,此时它不再可见,但是跟Paused状态一样保持着其所有状态信息及其成员变量。

Killed:

  当Activity被系统回收掉时,Activity就处于Killed状态。

  Activity会在以上四种形态中相互切换,至于如何切换,这因用户的操作不同而异。了解了Activity的4种形态后,我们就来聊聊Activity的生命周期。

Activity的生命周期

生命周期流程图

生命周期流程图

  该生命周期图说明了这些循环以及 Activity 在状态转变期间可能经过的路径。矩形表示回调方法,当 Activity 在不同状态之间转变时,您可以实现这些方法来执行操作。

  相信大部分Android开发对这张流程图并不陌生,我们下面主要聊得话题就是围绕这张流程图了。我们先有个大概印象,后面我们分析完后再回来看,就相当清晰了。

实现生命周期回调

  所谓的生命周期就是在有用户参与的情况下,Activity经历从创建,运行,停止,销毁等正常的生命周期过程。我们这里先来介绍一下几个主要方法的调用时机,然后再通过代码层面来验证其调用流程。

onCreate :

  该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。

onStart :

  此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见。

onResume :

  当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause方法和onStop方法被调用),重新回到前台时也会调用onResume方法,因此我们也可以在onResume方法中初始化一些资源,比如重新初始化在onPause或者onStop方法中释放的资源。

onPause :

  此方法被回调时则表示Activity正在停止(Paused形态),一般情况下onStop方法会紧接着被回调。但通过流程图我们还可以看到一种情况是onPause方法执行后直接执行了onResume方法,这属于比较极端的现象了,这可能是用户操作使当前Activity退居后台后又迅速地再回到到当前的Activity,此时onResume方法就会被回调。当然,在onPause方法中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause方法执行完成后,新Activity的onResume方法才会被执行。

onStop :

  一般在onPause方法执行完成直接执行,表示Activity即将停止或者完全被覆盖(Stopped形态),此时Activity不可见,仅在后台运行。同样地,在onStop方法可以做一些资源释放的操作(不能太耗时)。

onRestart :

  表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前Activity页面时,onRestart方法就会被回调。

onDestroy :

  此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。
下面我们通过程序来验证上面流程中的几种比较重要的情况,同时观察生命周期方法的回调时机。

示例

  当一个 Activity 转入和转出上述不同状态时,系统会通过各种回调方法向其发出通知。 所有回调方法都是挂钩,您可以在 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
25
26
27
28
29
30
31
32
public class ExampleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
}

注:正如以上示例所示,您在实现这些生命周期方法时必须始终先调用超类实现,然后再执行任何操作。

生命周期的流程

  这些方法共同定义 Activity 的整个生命周期。您可以通过实现这些方法监控 Activity 生命周期中的三个嵌套循环:

  • Activity 的整个生命周期

  发生在 onCreate() 调用与 onDestroy() 调用之间。您的 Activity 应在 onCreate() 中执行“全局”状态设置(例如定义布局),并在 onDestroy() 中释放所有无用的资源。例如,如果您的 Activity 有一个在后台运行的线程,用于从网络上下载数据,它可能会在 onCreate() 中创建该线程,然后在 onDestroy() 中停止该线程。

  • Activity 的可见生命周期

  发生在 onStart() 调用与 onStop() 调用之间。在这段时间,用户可以在屏幕上看到 Activity 并与其交互。 例如,当一个新 Activity 启动,并且此 Activity 不再可见时,系统会调用 onStop()。您可以在调用这两个方法之间保留向用户显示 Activity 所需的资源。 例如,您可以在 onStart() 中注册一个 BroadcastReceiver 以监控影响 UI 的变化,并在用户无法再看到您显示的内容时在 onStop() 中将其取消注册。在 Activity 的整个生命周期,当 Activity 在对用户可见和隐藏两种状态中交替变化时,系统可能会多次调用 onStart() 和 onStop()。

  • Activity 的前台生命周期

  发生在 onResume() 调用与 onPause() 调用之间。在这段时间,Activity 位于屏幕上的所有其他 Activity 之前,并具有用户输入焦点。 Activity 可频繁转入和转出前台。例如,当设备转入休眠状态或出现对话框时,系统会调用 onPause()。 由于此状态可能经常发生转变,因此这两个方法中应采用适度轻量级的代码,以避免因转变速度慢而让用户等待。

保存 Activity 状态

  当 Activity 暂停或停止时,Activity 对象仍保留在内存中,即有关其成员和当前状态的所有信息仍处于活动状态。 因此,用户在 Activity 内所做的任何更改都会得到保留,这样一来,当 Activity 返回前台(当它“继续”)时,这些更改仍然存在。

  不过,当系统为了恢复内存而销毁某项 Activity 时,Activity 对象也会被销毁,因此系统在继续 Activity 时根本无法让其状态保持完好,而是必须在用户返回 Activity 时重建 Activity 对象。但用户并不知道系统销毁 Activity 后又对其进行了重建,因此他们很可能认为 Activity 状态毫无变化。 在这种情况下,您可以实现另一个回调方法onSaveInstanceState(),对有关 Activity 状态的信息进行保存,以确保有关 Activity 状态的重要信息得到保留。

  系统会先调用 onSaveInstanceState(),然后再使 Activity 销毁。系统会向该方法传递一个 Bundle,您可以在其中使用 putString() 和 putInt() 等方法以名称和值对应形式保存有关 Activity 状态的信息。然后,如果系统终止您的应用进程,并且用户返回您的 Activity,则系统会重建该 Activity,并将 Bundle 同时传递给 onCreate() 和 onRestoreInstanceState()。您可以使用上述任一方法从 Bundle 提取您保存的状态并恢复该 Activity 状态。如果没有状态信息需要恢复,则传递给您的 Bundle 是空值(如果是首次创建该 Activity,就会出现这种情况)。

  下图(Activity 状态保存周期图)在两种情况下,Activity 重获用户焦点时可保持状态完好:系统在销毁 Activity 后重建 Activity,Activity 必须恢复之前保存的状态;系统停止 Activity 后继续执行 Activity,并且 Activity 状态保持完好。

Activity 状态保存周期图

注:无法保证系统会在销毁您的 Activity 前调用 onSaveInstanceState(),因为存在不需要保存状态的情况(例如用户使用“返回”按钮离开您的 Activity 时,因为用户的行为是在显式关闭 Activity)。 如果系统调用 onSaveInstanceState(),它会在调用 onStop() 之前,并且可能会在调用 onPause() 之前进行调用。

  不过,即使您什么都不做,也不实现 onSaveInstanceState(),Activity 类的 onSaveInstanceState() 默认实现也会恢复部分 Activity 状态。具体地讲,默认实现会为布局中的每个 View 调用相应的 onSaveInstanceState() 方法,让每个视图都能提供有关自身的应保存信息。Android 框架中几乎每个 View 都会根据需要实现此方法,以便在重建 Activity 时自动保存和恢复对 UI 所做的任何可见更改。例如,EditText 保存用户输入的任何文本,CheckBox 保存复选框的选中或未选中状态。您只需为想要保存其状态的每个 View 提供一个唯一的 ID(通过 android:id 属性)。如果 View 没有 ID,则系统无法保存其状态。

您还可以通过将 android: saveEnabled 属性设置为 “false” 或通过调用 setSaveEnabled() 方法显式阻止布局内的视图保存其状态。您通常不应将该属性停用,但如果您想以不同方式恢复 Activity UI 的状态,就可能需要这样做。

  由于 onSaveInstanceState() 的默认实现有助于保存 UI 的状态,因此如果您为了保存更多状态信息而替换该方法,应始终先调用 onSaveInstanceState() 的超类实现,然后再执行任何操作。 同样,如果您替换 onRestoreInstanceState() 方法,也应调用它的父类实现,以便默认实现能够恢复视图状态。

注:由于无法保证系统会调用 onSaveInstanceState(),因此您只应利用它来记录 Activity 的瞬态(UI 的状态),切勿使用它来存储持久性数据,而应使用 onPause() 在用户离开 Activity 后存储持久性数据(例如应保存到数据库的数据)。

  您只需旋转设备,让屏幕方向发生变化,就能有效地测试您的应用的状态恢复能力。 当屏幕方向变化时,系统会销毁并重建 Activity,以便应用可供新屏幕配置使用的备用资源。 单凭这一理由,您的 Activity 在重建时能否完全恢复其状态就显得非常重要,因为用户在使用应用时经常需要旋转屏幕。

总结

Activity正常的生命周期

onCreate()→onStart()→onResume()→onPause()→onStop()→onDestroy()

Activity横竖屏切换的生命周期(带保存状态)

onSaveInstanceState()→onPause()→onStop()→onDestroy()→onCreate()→onStart()→onRestoreInstanceState()→onResume()

  横竖屏切换生命周期详解:比如我们在看视频,现在要从竖屏切换到横屏的时候,要先保存我们现在的状态(如:你看视频看到5分钟,要保存当前看了几分钟、当前缓存的进度等),也就是onSaveInstanceState;接着竖屏的Activity要失去焦点onPause;然后让它停止运行onStop;再销毁它onDestroy;接着再创建横屏的Activity onCreate;再让它运行onStart;然后要将之前保存了的状态取出来,onRestoreInstanceState;最后让横屏的Activity获得焦点onResume。

Activity跳转的生命周期有两种情况:

从 A 跳转到 B

  • 1、这种情况是:A 完全不可见

  A—–onPause

  B——————onCreate

  B——————onStart

  B——————onResume

  A—–onStop

  • 2、这种情况是:B是透明的

  A—–onPause

  B——————onCreate

  B——————onStart

  B——————onResume

因为B是透明的,我们还能看见A,所以不执行 A—–onStop。这两种情况的返回都是一样的:

按 back 键,从B返回A:

  B——————onPause

  A—–onRestart

  A—–onStart

  A—–onResume

  B——————onStop

  B——————onDestroy

转载请注明出处:www.leoyanblog.com

本文出自 LeoYan 的博客

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 LeoYan 即可关注。

Activity是什么?

  我们都知道 Android 中有四大组件(Activity 活动,Service 服务,Content Provider 内容提供者,BroadcastReceiver 广播接收器),Activity是我们用的最多也是最基本的组件,因为应用的所有操作都与用户相关,Activity 提供窗口来和用户进行交互。

  官方文档这么说:

Activity 是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。

Activity的基础知识

  • 一个应用通常由多个彼此松散联系的 Activity 组成。

  • Activity的返回栈机制

  一般会指定应用中的某个 Activity 为“主”Activity,即首次启动应用时呈现给用户的那个 Activity。 而且每个 Activity 均可启动另一个 Activity,以便执行不同的操作。

  每次新 Activity 启动时,系统会将其推送到返回栈上,并取得用户焦点。 前一 Activity 便会停止,但系统会在堆栈(“返回栈”)中保留该 Activity。 因此,当用户完成当前 Activity 并按“返回”按钮时,系统会从堆栈中将其弹出(并销毁),然后恢复前一 Activity。

注:关于“Activity的返回栈”的详细阐述,请看相关文章 Android之Activity(三)Task和LaunchMode

  • Activity的生命周期

  Activity的每一个状态变化,都会回调对应该状态的生命周期方法。

注:关于“Activity的返回栈”的详细阐述,请看相关文章 Android之Activity(二)生命周期

创建 Activity

  要创建 Activity,您必须创建 Activity 的子类(或使用其现有子类)。您需要在子类中实现 Activity 在其生命周期的回调方法。 两个最重要的回调方法是:

onCreate()

  您必须实现此方法。系统会在创建您的 Activity 时调用此方法。您应该在实现内初始化 Activity 的必需组件。 最重要的是,您必须在此方法内调用 setContentView(),以定义 Activity 用户界面的布局。

onPause()

  系统将此方法作为用户离开 Activity 的第一个信号(但并不总是意味着 Activity 会被销毁)进行调用。 您通常应该在此方法内确认在当前用户会话结束后仍然有效的任何更改(因为用户可能不会返回)。

  您还应使用几种其他生命周期回调方法,以便提供流畅的 Activity 间用户体验,以及处理导致您的 Activity 停止甚至被销毁的意外中断。 后文的管理 Activity 生命周期部分对所有生命周期回调方法进行了阐述。

实现用户界面

  Activity 的用户界面是由层级式视图(衍生自 View 类的对象)提供的。每个视图都控制 Activity 窗口内的特定矩形空间,可对用户交互作出响应。 例如,视图可以是在用户触摸时启动某项操作的按钮。

  您可以利用 Android 提供的许多现成View和Layout来设计和组织您的布局。“Widget”是提供按钮、文本字段、复选框或仅仅是一幅图像等屏幕视觉(交互式)元素的视图。 “Layout”是衍生自 ViewGroup 的视图,为其子视图提供唯一布局模型。 您还可以为 View 类和 ViewGroup 类创建子类(或使用其现有子类)来自行创建Widget和Layout,然后将它们应用于您的 Activity 布局。

  利用视图定义布局的最常见方法是借助保存在您的应用资源内的 XML 布局文件。这样一来,您就可以将用户界面的设计与定义 Activity 行为的源代码分开维护。 您可以通过 setContentView() 将布局设置为 Activity 的 UI,从而传递布局的资源 ID。不过,您也可以在 Activity 代码中创建新 View,并通过将新 View 插入 ViewGroup 来创建视图层次,然后通过将根 ViewGroup 传递到 setContentView() 来使用该布局。

在清单文件中声明

  Activity
您必须在清单文件中声明您的 Activity,这样系统才能访问它。 要声明您的 Activity,请打开您的清单文件,并将 元素添加为 元素的子项。例如:

1
2
3
4
5
6
7
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >

  您还可以在此元素中加入几个其他特性,以定义 Activity 标签、Activity 图标或风格主题等用于设置 Activity UI 风格的属性。 android:name 属性是唯一必需的属性,它指定 Activity 的类名。

使用 Intent 过滤器

   元素还可指定各种 Intent 过滤器(使用 元素)以声明其他应用组件激活它的方法。

  当您使用 Android SDK 工具创建新应用时,系统自动为您创建的主 Activity 包含一个 Intent 过滤器,其中声明了该 Activity 响应“主”操作且应置于“launcher”类别内。 Intent 过滤器的内容如下所示:

1
2
3
4
5
6
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

   元素指定这是应用的“主”入口点。 元素指定此 Activity 应列入系统的应用启动器内(以便用户启动该 Activity)。

  如果您打算让应用成为独立应用,不允许其他应用激活其 Activity,则您不需要任何其他 Intent 过滤器。 正如前例所示,只应有一个 Activity 具有“主”操作和“launcher”类别。

  不过,如果您想让 Activity 对衍生自其他应用(以及您的自有应用)的隐式 Intent 作出响应,则必须为 Activity 定义其他 Intent 过滤器。 对于您想要作出响应的每一个 Intent 类型,您都必须加入相应的 ,其中包括一个 元素,还可选择性地包括一个 元素和/或一个 元素。这些元素指定您的 Activity 可以响应的 Intent 类型。

启动 Activity

  您可以通过调用 startActivity(),并将其传递给描述您想启动的 Activity 的 Intent 来启动另一个 Activity。Intent 对象会指定您想启动的具体 Activity 或描述您想执行的操作类型(系统会为您选择合适的 Activity,甚至是来自其他应用的 Activity)。 Intent 对象还可能携带少量供所启动 Activity 使用的数据。

  在您的自有应用内工作时,您经常只需要启动某个已知 Activity。 您可以通过使用类名创建一个显式定义您想启动的 Activity 的 Intent 对象来实现此目的。 例如,可以通过以下代码让一个 Activity 启动另一个名为 SignInActivity 的 Activity:

1
2
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

  不过,您的应用可能还需要利用您的 Activity 数据执行某项操作,例如发送电子邮件、短信或状态更新。 在这种情况下,您的应用自身可能不具有执行此类操作所需的 Activity,因此您可以改为利用设备上其他应用提供的 Activity 为您执行这些操作。 这便是 Intent 对象的真正价值所在。您可以创建一个 Intent 对象,对您想执行的操作进行描述,系统会从其他应用启动相应的 Activity。 如果有多个 Activity 可以处理 Intent,则用户可以选择要使用哪一个。 例如,如果您想允许用户发送电子邮件,可以创建以下 Intent:

1
2
3
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

  添加到 Intent 中的 EXTRA_EMAIL,extra 是一个字符串数组,其中包含应将电子邮件发送到的电子邮件地址。 当电子邮件应用响应此 Intent 时,它会读取 extra 中提供的字符串数组,并将它们放入电子邮件撰写窗体的“收件人”字段。 在这种情况下,电子邮件应用的 Activity 启动,并且当用户完成操作时,您的 Activity 会恢复执行。

启动 Activity 以获得结果

  有时,您可能需要从启动的 Activity 获得结果。在这种情况下,请通过调用 startActivityForResult()(而非 startActivity())来启动 Activity。 要想在随后收到后续 Activity 的结果,请实现 onActivityResult() 回调方法。 当后续 Activity 完成时,它会使用 Intent 向您的 onActivityResult() 方法返回结果。

  例如,您可能希望用户选取其中一位联系人,以便您的 Activity 对该联系人中的信息执行某项操作。 您可以通过以下代码创建此类 Intent 并处理结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}

  上例显示的是,您在处理 Activity 结果时应该在 onActivityResult() 方法中使用的基本逻辑。 第一个条件检查请求是否成功(如果成功,则resultCode 将为 RESULT_OK)以及此结果响应的请求是否已知(在此情况下,requestCode与随 startActivityForResult() 发送的第二个参数匹配)。 代码通过查询 Intent 中返回的数据(data 参数)从该处开始处理 Activity 结果。

  实际情况是,ContentResolver 对一个内容提供程序执行查询,后者返回一个 Cursor,让查询的数据能够被读取。

结束 Activity

  您可以通过调用 Activity 的 finish() 方法来结束该 Activity。您还可以通过调用 finishActivity() 结束您之前启动的另一个 Activity。

注:调用这些方法可能对预期的用户体验产生不良影响,因此只应在您确实不想让用户返回此 Activity 实例时使用。

声明: 本文是转载的网络文章, 出处为公众号”伯乐在线”, 在此表示感谢

没有读者,写技术博客文章感觉不到太多的作用,是浪费时间的事情,是这样吗?

不是。

发布有关软件技术的博客将带来数以千计的美元,尽管没有人曾读您的博客。闲话少叙,首先,读者可能是写博客的目标,但他们实际上是自然的结果。一路上还有很多其他的个人利益,包括更好的工作。

深刻理解自己的想法

有人说,“你不能真正理解一件事,除非你可以将它解释给你的祖母”。不要试图将他们的意见详述在文本文件上。

在写有关软件的技术博客时,要注意的第一点仅仅是我们的想法有多么不完整。我们是概念性的生物,对软件的理解是抽象的。我们依靠直觉在脑海中填充空白的部分。

在很多方面,我们对于软件的感受像梦一样:在积极参与的时候,它们是有意义的。但在试图抄录的时候,将发现哪里都有洞。那并不是说它们是不切实际或是矛盾的,仅仅是……不完整。

写博客促使一些时间花费在填补空白上。填补空白使得您能够严格地思考自己的意见。这些活动的结果是对之前以为已经充分了解的主题有了更深入的理解。这也体现在外部。您将发现自己对于主题的谈论更为透彻和自信,甚至同博客文章的内容密切相关。

学会沟通

有两种方式可以传达意见:从自己的角度或从对方的角度。前者很容易,但没有用。记得那些杰出、但没有人理解的高校教授吗?他们不是从学生的角度来教学的。结果是他们的光彩失去了观众。

作为一个领域的专家,应当注意避免这一点。我们不受某些软件的使用权保护。人们花费时间阅读博客来学习新的思想,扩展他们的视野,并紧跟技术的潮流。学习如何有效地传递想法给任何观众,是令您的观点平易近人的重要组成部分。那也使您成为一个更好的传播者。

自从开始写博客,我的口语交际能力得到了提升。不是因为我曾学着 ”不动声色地做事“。学习注意哪些细节是合适的那些不是。学习从读者的角度解释概念。这些改变了同事甚至是客户如何理解您对主题的掌握。

构建可信的任职资格

我假设有关博客作者的一件事是,他们知道自己的过失。我的意思是,他们必须知道。他们的博客有数百篇文章,那不仅仅是……碰巧发生。

但是那仅仅是……碰巧发生。任何写过一定数量博客的人都知道他们的过失。因果关系在这里扮演着角色。

开始写博客并不需要你获得通过什么测试或获得相关的证书。博客作者十分了解他们所在领域的知识,这正他们通过写博客获取的益处。写的博客文章越多,越能填补理解上的空白,在沟通上越熟练。

装备更好的理解和沟通技巧,客户关系提升。在团队中将占据更有价值的位置。面试似乎变得更简单了,您能够指示人们通过您的博客方向跳过很多技术面试中用来判断你任职资格的繁琐的问题。更好的理解力,使得一个员工更有价值。更有价值,则可寻得更好的工作。更好的工作具有更多的薪资。一件迷人的事情。

开始一篇博客

对于那些刚开始写博客的人,因为你没有读者,所以写博客似乎让你看不到什么成功的希望。人们很少知道,读者是催生博客的动力燃料他们是汽车里的油,并不是我们将要到达的目的地。

我会再写一篇有关于如何获取读者和设置博客的文章。对那些渴望开始写博客(对您有好处!)的人,我为您指出 Ghost 和其中的一些免费主题。它免费、开源、在 Markdown 运行,并且有良好的文档使其运行。

事实上,我非常喜欢 Ghost ,甚至已经下载了它为有写博客需求的人所提供的客户端。

我认为这是博客的另一个好处。当然,好处还有很多很多。

在获得第一个读者或广告收入之前的很久一段时间内,博客具有宝贵的经验教训。这是最重要的。

相关阅读

声明: 本文是转载的网络文章, 出处为公众号”伯乐在线”, 在此表示感谢

上次推荐了《为什么有些技术人员不写博客?》,原作者分享了一些原因。今天我们推荐本篇博客,推荐大家写博客的一些理由。以下是正文:

本文只代表个人见解,不代表任立场,如果您认为我的想法是错的那很正常,因为这是我的想法,如果您觉得您的想法和我一样,那我们就是传说中的 “激友”(对生活冲满激情的朋友)。

我心中的博客

我所以指的写博客,不单只是写一篇文章出来这一结果。而应该是写的这一过程,写过技术文章的朋友应该跟我一样有这么一个过程。

  1. 自己了解学习,文章所涉及到的知识点,及知识点衍生出来的知识点。

  2. 对学习的知识点进行验证,以确保理论值与实践值保持一致

  3. 构思文章的大纲,哪些部分需要重点写,需要配合实例代码,图片等信息

  4. 动手写,写完后再次检查校正并排版,然后发表

  5. 针对网友的评论中提出的问题进行回复

我写文章一般都会经历以上5上步,最终以上5步融合成一个结果那就是”一篇文章” 这一过程也是我心中对的”写博客”一词的诠释

为什么要写博客

为自己

写博客对自己的提升是很大的,可能写一篇体现不出来,但是只要你坚持写效果就很明显,好处人个认为有以下几点

强化知识点:

在写一篇文章前,你必定是要把以文章中心为主的知识点及衍生的知识点都详细了解一篇,在这一过程中必须会涉及到自己以前所了解过的知识,人的记忆是存在记忆曲线的需要不断的重复记忆才能长久的记住某一事物,而每写一篇文章时都会查阅资料,在这一过程中必然会遇到以前记住了而现在渐渐淡忘的知识点,当你再次看到时瞬间就会回想起,此时以前的知识点就得到了强化。

提升学习能力:

同一样的人,了解同一知识点,用不同的方法,产生的结果必然会不一样,找到最佳的学习方法,这也是一种能力,这种能力是经过多次实践探索之后总结出来的,以前我每次需了解某一种技术时都会先百度看各种搜索结果,发现没有想要的之后,再Google因为Google的结果与百度的会有所不同,Google结果中国外的文章相对会多一点,而偶然点了一个链接进入了博客园,发现就是自己想要的东西,而且把概念,代码,及经验都写上去了,看完之后对我帮助很大。

渐渐的我便开始采这种方法了解新知识概念性的直接看百度百科,实质性的直接 上博客园的 找找看 ,群里的朋友还推荐了一种方法,比如我要学MVC 园子里很多人都写了 关于MVC的一系列文章,把那一系列的文章都看一遍,对于MVC就基本有了了解了,这便是学习能力的提升,对于某种技术用最短的时间做到了比较全面的了解

提升文字组织能力:

这个就不用说了,写博客,既然是写,就必然会有大量的文字,而如何组织文字表达出自己想表达的意思,是长期练习的,而写博客正好帮助你提高了你的文字组织能力,

提升逻辑思维能力:

不用说,技术性的东西从来就没的单独存在的,都一层层技术相结合,那在了解某种技术时,自己的思维也是要顺着这种关系逐渐深入的,比如MVC,你不能只知道 M是什么V是什么 C是什么就行了吧,你得知道 M V C 这三者关系是怎样的,又是怎样交互,而你了解之后再把它写出来时,需要清晰逻辑。

为他人
有意的:

园子里有很多人都写过关于 MVC 框架 WCF 等等系列文章,目的就在于帮助新人快速上手,这个我深有体会,当初我开始学习MVC时就是看的T2噬菌体的MVC系列文章,整篇看完后再配合自己动手对于MVC就有了基本的了解了,在次感谢园子里无私献的大牛们。而以上行为就是有意的帮助。

无意的:

很多时候在开发项目的过程中,遇到了技术问题,花了时间解决后,有人会写博客记录,并附上解决方法旨在当再次遇到问题时直接看下文章就知道如何处理了。

而碰巧的是,这种问题不止他一个人遇到了。很多人在开发时也遇到了这个问题,在网上找答案时,就找到了这篇文章,并根据文章提供的解决方法,顺利的解决了问题,这种帮助就是无意的帮助

一定要写博客吗

答案肯定是否定的,中国几百万的程序员,如果都写博客,那程序员的春天就来了,但是事实并非如此。而我所讲的 写博客 的产物并不只是一篇文章,更多的是,对自己能力的提升,自己对知识点的总结,而发表在博客上只是为了公开,还有很多人喜欢记录在云笔记里面。还有工作很忙,没有空闲时间写出来,因为写技术性的文章,花的时间是很长的。写过的朋友都知道。

博客会给你带来哪些收获

古人云:一份耕耘,一份收获

以下这些是帮助他人而得到的一些认可,并非主观上去追求的

MVP:微软每年都颁发MVP给那些经常与其他专业人士分享知识和专业技能,受人尊敬、信任,而且平易近人的专家。而这个称号则是对你写的博客质量的肯定

知名度:文章写得好的人,技术水平肯定也很好,知道的人多了,知名度就有了,比如园子里排名前10的大家都知道,都看过他们的文章。

尊敬:对于技术界的大神,都是受人敬仰的,在园子里或者工作中也是一样的,在心里对大神们都是默默的佩服!至少我是这样啦,哈哈~也是我学习的榜样!

总结

我所认的写博客是对自己所了解知识的强化,分享,自身能力的提升。当然 写 博客只是一种方法而以,只要能达到提升自我的效果什么方法都是可以的

之前有看过一篇文章:《即便没有读者,你也要写博客》 ,其中也讲解了很多写博客的好处。

而我写博客是希望,能提升自己的综合能力,并把自己的知识与经验分享给大家,如果有幸我的分享帮助了一些人,那将使我更加欣慰。

最后附上一句名言:有些事情你现在不去做,可能以后都不会有机会了!

注:我代表不了大家,所以以上观点只代表我个人。

相关阅读

声明: 本文是转载的网络文章, 出处为公众号”伯乐在线”, 在此表示感谢

常有人跟我讨论我在blog上发布过的博文,有时候他们还希望我来撰写某些文章。在讨论的过程中,我几乎总是会问为什么你自己不开一个博客,或者为其他人的博客做些贡献呢?当我在引导他们为技术类的主题写一些博文时,极少有人对此感兴趣。

我的母亲总是告诉我(以及她的学生们)每个人都有自己的故事。她说,写作可能是一种你不曾想到过的非常有益处的行为,直到你写的东西获得了其他人的喜爱和赞同。就像软件开发者为他们的用户开发软件一样,作家为他们的读者而写作。从来都没有什么论断说技术人员无法成为激励他人学习并乐于同他人分享知识的优秀作者。

我写这篇博文的目的就是想鼓励广大的技术人员去享受写作、高效的写作,并能够从中得到乐趣。我将翻出一些我曾经最常见到的关于为什么技术人员不愿意写博客的理由。

“我不认为我是某方面的专家。对于任何一个我能想到的主题,我都不是权威。”

我首先想到的是这个理由,因为它将是我最需要去驳斥的观点。如果从这篇博文里你没有得到任何收获的话,那就记住这句话:你并不需要成为某方面的专家才能去写相关的文章。

翻翻我的博客你就能找到很多这样的例子。我自认为自己是某个方面,或者某两个方面的专家,但我在过去5年中写了超过450篇博文,我肯定不会只写我最在行的那一两个主题。写下你懂得的东西,要成为权威你就不能害怕去多做些研究。这方面有一个很好的例子就是我的一篇标题为“Kerberos for haters”的博文。我几乎没有任何有关Kerberos方面的经验。事实上,甚至在我的RHCA(RedHat系统部署工程师)认证考试中我都无法正确配置好它!但是,我对此做了相当多的研究,并开始慢慢理解了这一大坨东西是如何联系起来的。还有许多人都对Kerberos感到困惑,于是我决定将我所掌握的有关Kerberos方面的知识串接起来写成一篇博文。这篇博文引来了许多正面和负面的回复,很明显我发布的博文对一些读者起到了帮助作用,启发了一些人同时也得罪了一些人。

接下来看看下一个常遇到的理由:
如果我写的东西里面有些地方是错误的怎么办?在整个互联网面前犯错,这使我看起来就像是个傻瓜。

这种事我早就经历过,都已经有些厌倦了。做个不恰当的假设,每个作者都至少会犯一次错。读者们会指出你的错误(有些读者会很含蓄的指出,而有些读者不会这样),下面就是你的责任了,要么更正你的大作要么说服你的读者是他们错了。我自己也曾经发表过含有错误的博文,而且我对于时不时的要去检查这些错误显得有些懒惰。就像我中学时的新闻学老师一直教导我的:对于一个错误,最重要的部分是你要如何去更正它,并从中汲取教训。总之,你一定会犯些错误的。只要你尽心尽力的对此做研究,并尽量减少错误,及时对错误做出回应,我想读者是不会怪您的。

说到错误,这里还有一个常见的理由:
我技术还不错,但我的拼写和语法很糟糕,我根本不擅长写作。

这个问题很容易解决,如果你是那种什么事情都靠自己解决的人,那就拿起这本由Strunk和White合著的《The Elements of Style | 风格的要素》吧。网上有这本书的PDF版,或者你也可以借一本来读。无论你属于哪种情况,这本书详尽的描述了应该如何适当的加标点符号、如何组织句子和段落,以及如何正确地引用你的论点来源(对于写研究性的文章来说相当受用)。也许你并不想拿起一本如此枯燥的参考书来读,如果是这样的话,看看你身边有没有擅长写作的人。在大公司里你常常能在市场部或者公司的通讯录里找到一些愿意读你的文章并帮你做批注的伙计(谢谢你Garrett!,感谢你曾经为我修订过文章)。在 Fiverr(著名的5美元服务区,这是一个在线的信息平台,特色之处在于其收集那些价值5美元的事情,用户可以发布、接受或者分享这些信息)上我甚至找到了一些愿意以5美元的价格为我修订文章的人。

下面我们将看看这第二常见的理由:
我不知道该写给谁看。如果我写的东西太简单了,那些真正的技术大牛们会不会觉得我就是个小白?如果我写的东西超级复杂,大多数人都接受不了又怎么办?

这些我都经历过。大多数称职的Linux系统管理员都知道该如何添加和删除iptable规则,他们会觉得这是相当简单的任务。但是你知道吗,在我写过的超过450篇的博文里,这篇《deleting a single iptable rule》的访问量每个月都是排名前5!我每个月的点击量里有11%都来自这篇博文。人们要么通过这篇博文学到了一些知识,要么是他们忘记了该如何删除一条iptable规则,想通过这篇博文做快速的参考。不管如何,这篇博文对于许多人来说都是很有价值的,尽管在我看来这个主题相当的简单。反过来说,我曾经发疯写过一个完整的关于云主机冗余配置的how-to类文档,结合了LVS、glusterfs、MySQL on DRBD、memcached、haproxy以及Idirectord等各种技术。我觉得对于某些读者来说这个文档会很有价值,但肯定会搞晕绝大部分读者。事实证明我又错了,这篇博文长期占据我博客的前10名受欢迎的文章之一,通过这篇博文我收到的回复、email和IRC比其他的文章都要多。这再次证明,本是一篇我认为最没有用处的文章反倒成为了一个“话匣子”。

最后,让我们总结一下,如果你对于写作感到力不从心或者觉得气馁的话,记住下面这些忠告:
  • 写你感兴趣的东西,不必在意你是否是专家
  • 不要害怕失败
  • 多多回复你的读者
  • 就算你觉得没人会看你写的东西,也要坚持写下去
  • 始终确保你的文章就代表着你的声音——这也是为什么写作是如此特别和吸引人的地方

相关阅读

转载请注明出处:www.leoyanblog.com

本文出自 LeoYan 的博客

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 LeoYan 即可关注。

简单总结了一下 Android App 开发中使用到的知识,以脑图的形式呈现。后续会慢慢补全各个分支相应的链接。

Android-App开发技能图谱

注:如图片显示不清晰,请在图片上右键另存为到本地查看高清大图。

一、开发工具

1. IDE

  • Android Studio
  • Eclipse

2. 调试工具

Android Tools

  • adb
  • Hierarchy Viewer
  • draw9patch
  • UI Automator Viewer
  • Trace View
  • Lint

网络调试

  • Charles
  • Wireshark
  • Fiddler
  • tcpdump
  • Paw/Postman

内存分析

  • Android Monitor
  • MAT

3. 版本控制

Git

  • Git命令
  • Github/GitLab

SVN

4. CodeReview

  • Gerrit
  • Github pull request

5. Bug/任务管理

  • Redmine
  • JIRA
  • Bugzilla
  • Teambition
  • Tower

6. 编译工具

  • Gradle

7. 持续集成

  • Jenkins
  • Travis CI

8. 应用分发

  • 蒲公英
  • fir.im

二、App 基础

1. 基础知识

  • java基础
  • 数据结构
  • 面向对象思想
  • 设计模式
  • 面向对象思想

2. Android基础

Android SDK

基本组件

  • Activity
  • Service
  • BroadcastReceiver
  • ContentProvider
  • Intent/Intent Filter
  • AndroidMainfest

UI

Layout
  • LinearLayout
  • RelativeLayout
  • FrameLayout
  • GridLayout
  • TableLayout
  • DrawerLayout
  • SlidingPaneLayout
View
Widget
  • TextView
  • Button
  • ImageView
  • ImageButton
  • RadioButton
  • ToggleButton
  • CheckBox
  • Switch
  • ProgressBar
  • SeekBar
  • RatingBar
  • Spinner
  • WebView
Container
  • RadioGroup
  • ScrollView
  • ListView
  • GridView
  • ExpandableListView
  • Gallery
  • ViewPager
  • SlidingDrawer
  • TabHost
  • VideoView
  • RecyclerView
  • CardView
Date&Time
  • DatePicker
  • TimePicker
  • CalendarView
  • TextClock
  • AnalogClock
  • Chronometer
Expert
  • ToolBar
  • Fragment
  • Space
  • PopupWindow
  • CheckedTextView
  • AutoCompleteTextView
  • MultiAutoCompleteTextView
  • QuickContactBadge
  • ExtractEditText
  • NumberPicker
  • ZoomButton
  • ZoomControls
  • GestureOverlayView
  • SurfaceView
  • TextureView
  • StackView
  • ViewStub
  • ViewAnimator
  • ViewFlipper
  • ViewSwitcher
  • ImageSwitcher
  • TextSwitcher
  • AdapterViewFlipper
  • MediaController
  • DialerFilter
  • PopMenu
Other
  • include
  • requestFocus
Custom View
  • extend system View
  • combination View
  • extend View
Animation
View Animation
  • Tween Animation
    • Alpha
    • Scale
    • Translate
    • Rotate
    • Interpolator
  • Frame Animation
    • animation-list
Property Animation
  • ValueAnimator
  • ObjectAnimator
  • AnimatorSet
Resource
assets
  • AssetManager
res
  • anim
  • animator
  • color
  • drawable
  • interpolator
  • layout
  • menu
  • raw
  • values
    • arrarys
    • attrs
    • bools
    • colors
    • string
    • styles
  • xml
OpenGL

3. 数据持久化

Sqlite

  • SQLiteOpenHelper
  • ContentProvider

File

  • Internal Storage
  • External Storage

SharedPreferences

4. 通信

Http

  • HttpClient
  • HttpConnection

Socket

Bluetooth

NFC

Headset

USB

5. 手机功能

电话

  • 联系人
  • 通话记录

短/彩信

Camera

Audio

SD卡

Wifi

感应器

  • 加速
  • 方向
  • 重力
  • 光线
  • 陀螺仪
  • 磁场
  • 接近
  • 温度
  • 压力
  • 线性加速度
  • 旋转

三、App 进阶

1. Process&Thread

Process

  • Linux进程
  • App进程原理

AIDL

  • 实现方式
  • 原理

Handler/Looper/MessageQueue/Thread

Loader

AsyncTask

2. 性能优化

  • ANR
  • 布局层级性能优化

3. 内存优化

  • 内存检测工具
  • 内存分析工具
  • Bitmap优化
  • 内存泄露查找及分析

4. 网络优化

API优化

低网速下优化

流量使用优化

  • 判断当前网络类型
  • 使用缓存

5. 单元测试

  • JUnit

四、App 高级

1. 相关原理熟悉

Activity

  • 启动流程
  • 生命周期回调原理
  • 与View/Window的关系
  • 与Fragment的关系

View/Window

  • View/Window关系
  • View渲染
  • View事件分发机制

编译打包

  • 编译打包原理
  • 逆向工程分析
  • 热修复

2. Hybrid App

与Native App的异同

主流框架

  • React Native
  • Weex
  • PhoneGap
  • ionic

3. 架构能力

架构

  • MVC
  • MVP
  • MVVM
  • Flux
  • Clean Architecture

App框架

  • 分包
  • 分层

设计模式

  • OOD原则
  • 常用设计模式运用

4. ART&Dalvik

  • AOT compilation
  • GC
  • Bytecode&Dex

5. 自动化测试

  • Monkey/MonkeyRunner
  • UIAutomator
  • Espersso
  • Robotium
  • Appium
  • Athrun(TMTS)

五、扩展学习

1. 响应式编程

Rx

  • RxJava
  • RxAndroid
  • RxBinding

Agera

2. 快速开发

  • ButterKnife
  • Android Annotation
  • AFinal
  • xUtils

3. Views

  • 太多…

4. 网络请求

  • OkHttp
  • Retrofit
  • Volley

5. 图片请求

  • Glide
  • Fresco
  • Picasso
  • Universal-Image-Loader

6. 依赖注入

  • Dagger2

7. 事件总线

  • EventBus
  • Otto

8. 数据库

  • ORMLite
  • GreenDAO
  • Realm
  • SugarORM
  • ActiveAndroid

9. 图表

  • MPAndroidChart
  • HelloCharts

10. 辅助

  • Logger
  • LeakCanary
  • DbInspector

11. 支付

  • 支付宝
  • 微信
  • 银联
  • Ping++

12. 地图

  • 百度地图
  • 高德地图
  • Google地图

13. 分享

  • ShareSDK
  • 友盟Ushare

14. 统计分析

  • 友盟

15. 语音识别

  • 科大讯飞

16. 人脸识别

  • Face++
  • ReadFace

17. 广告


基本信息

作者

  • LeoYan

日期

  • 2017/02/16

联系我

回顾2016

2016终于过去了,总的来说,这一年运气比较背。

3月份正式离职,经历了漫长的8个月空窗期。期间经历了很多事,腿被烫伤,重感冒加上火。感觉把从小到大的霉运都攒到了这一年来还给我一样。否极泰来,7月末,烫伤痊愈。9月末,重感冒痊愈,肺火已消。10月末,终于找到了合适的工作,在此还要多谢明哥。12月份,转正,踏实工作。

在找工作这段日子,意识到个问题。为什么记不起三个月之前学过什么?原因是否为经常碎片化的学习却不做整理、总结和记录?既然这样,那要用什么方式对所学的知识点技术点做一个系统的整理、总结和记录呢?我的想法:写博客!!!既然萌生想法,就要抓紧时间落实。11月份,刚开始新的工作,无暇顾及其他。12月份,工作之余,尝试着搭建起自己的个人博客。至此,2016结束,2017开始。

计划2017

作为一名“非高级Android开发工程师”,未来的路还很长,需要学习的还很多,这个博客对于我来说,是对自己所学知识的整理、总结和记录。当然,人无完人,对于一些错字啊、记录错误啊、对知识点的理解错误啊,还劳烦各位大师大侠留言指出,小生及时改正。如果有幸我的记录分享在未来对一些人有帮助的话,也算是鄙人的一大幸事了。下面为暂时粗略的计划,未来可能会调整或细化。

每周一篇技术博客

内容包括软件开发的各种技术知识点,包括原创和转载

要求:

  1. 确保自己先把该技能点学习透彻
  2. 尽量把互相关联的知识点都链接到
  3. 输出的内容尽量通俗易懂

其他博客

内容包括但不限于读书笔记、生活记录、人生感悟

总结

希望自己可以坚持下来,并且通过对知识的整理、总结和记录把自己的开发技能提升起来,早点把“非高级Android开发工程师”这个职位名称中的“非”字去掉。

一、

  • 哈哈
  • 咋的
    • 我是已选

      再试试这个引用
      我是引用第二行

我是删除线

==我是有背景的==

我是斜体

我是加粗

++我是下划线++


上面是分割线

1
2
3
public class Demo extends Object {

}
表头 1 表头 2 表头 3
1 行 1 列 1 行 2 列 1 行 3 列
2 行 1 列 2 行 2 列 2 行 3 列
3 行 1 列 3 行 2 列 3 行 3 列

image 测试图片

测试链接

下面测试函数

1
E = mc^2
1
x^2 = 4

下面测试graph图标哈

1
2
graph LR
A-->B

下面测试sequenceDiagram序列图

1
2
3
sequenceDiagram
A->>B: How are you?
B->>A: Great!

下面测试甘特图gantt(任务进度表)

1
2
3
4
5
6
7
8
gantt
dateFormat YYYY-MM-DD
section Android
T1: 2014-01-01, 1d
section IOS
T2: 2014-01-11, 9d
section 后台
T3: 2014-01-02, 9d

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment