课程 3B: 面向对象编程

这节课是 Android 开发(入门)课程 的第一部分《布局和交互》的最后一节课,导师是 Katherine Kuan 和 Kunal Chawla,主要内容是更多的 XML 布局与 Java 代码,完善 Just Java App。这节课出现了很多第一次应用的 Views,但在掌握了高效的学习方法的情况下,可以体验到快速上手的感觉,下面就带领大家开始。

关键词:CheckBox、ScrollView、EditText、strings.xml、styles.xml,if-else 流控语句、Intent

CheckBox
  1. Google 搜索 "checkbox android" 第一个结果是 Android 文档;第二个结果是代码示例,也可以在 Common Android Views Cheat Sheets 中找到。

  2. Just Java App 中的 CheckBox 代码如下:

<CheckBox
   android:id="@+id/whipped_cream_checkbox"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginBottom="8dp"
   android:paddingEnd="24dp"
   android:paddingStart="24dp"
   android:text="@string/whipped_cream"
   android:textSize="16sp" />

CheckBox 是 TextView 的子 class,所以拥有 TextView 的属性,如 android:text。其中,

   android:paddingEnd="24dp"
   android:paddingStart="24dp"

将勾选框和文字分开 24dp。paddingStart 应用于从左往右的视图,paddingEnd 应用于从右往左的视图。

  1. CheckBox 是一个对象,它有一个布尔 (Boolean) 类型的的变量来保存勾选框的状态,显然只有真 (true) 或假 (false) 两种,也就是说布尔变量只有两个值。Google 搜索 "java data type" 查找 Java 的基本数据类型 (Primitive Data Types) 进一步了解。

  2. Just Java App 中的 CheckBox 对象如下:

CheckBox whippedCreamCheckBox = (CheckBox) findViewById(R.id.whipped_cream_checkbox);
boolean hasWhippedCream = whippedCreamCheckBox.isChecked();
//Log.v("MainActivity", "Has whipped cream:" + hasWhippedCream);

(1)布尔变量名同样遵循变量命名规则,常以 has 或 is 开头,如 hasWhippedCream。
(2)在调试时将信息打印到 logcat 中,能检查代码的运行情况。格式:

Log.v(“class名”, “字符串”);
  • 注意打印信息的长度,避免刷屏刷掉错误等重要信息。调试结束后可将此行注释掉。
  • 布尔变量与字符串连接会变成字符串 true 或 false,如 "Has whipped cream: " + hasWhippedCream → Has whipped cream: true 或 Has whipped cream: false。
ScrollView

Google 搜索 "how to scroll in android app" 找到 stack overflow 论坛的结果:利用 ScrollView 实现屏幕垂直方向滚动。这对设备横屏状态下非常有用。ScrollView 只能有一个子 View,Just Java App 中的 ScrollView 如下:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.example.android.justjava.MainActivity">
   …
</ScrollView>

fill_parent 是 match_parent 的旧版本写法。

EditText
  1. Google 搜索 "user input android" 找到 Best Practices for User Input 结果,选择 Keyboard Input 可找到 EditText 的代码示例,也可以在 Common Android Views Cheat Sheets 中找到。

  2. EditText 允许用户在 App 中输入文字,Just Java App 中的 EditText 如下:

<EditText
   android:id="@+id/name_field"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:hint="@string/name"
   android:inputType="textCapWords" />

在 Android 文档中查找 EditText 的属性含义。

  • android:hint 设置在 EditText 无输入时显示的提示文字。
  • android:inputType 设置文字在 EditText 中的显示方式,textCapWords 表示每个单词首字母自动大写,但对 Google 拼音输入法无效。
  1. Google 搜索 "how do i get text from edittext field android" 找到 stack overflow 论坛的结果:通过链式调用 EditText 的 methods 来获取 EditText 中的文字。

  2. Just Java App 中的 EditText 对象如下:

EditText nameField = (EditText) findViewById(R.id.name_field);
String name = nameField.getText().toString();
//Log.v("MainActivity", "Name: " + name);

getText() 的返回值类型为 Editable 对象,进一步调用 toString() 确定返回值为字符串。

strings.xml
  1. 在 Android Studio 中左侧 Project 标签 Android 视图下 app→res→values→strings.xml 文件应保存 App 的所有字符串资源,所以应将先前硬编码的字符串取到 strings.xml 中。
  2. Just Java App 中的 strings.xml 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <!-- Title for the application. [CHAR LIMIT=12] -->
   <string name="app_name">Just Java</string>

   <!-- Hint text display in the empty field for the user's name [CHAR LIMIT=20] -->
   <string name="name">Name</string>
   <string name="toppings">Toppings</string>
   <string name="whipped_cream">Whipped Cream</string>
   <string name="chocolate">Chocolate</string>
   <string name="quantity">Quantity</string>
   <string name="decrement">-</string>
   <string name="initial_quantity_value">1</string>
   <string name="increment">+</string>
   <string name="order">Order</string>

   <!--
     Name for the order summary. It will be shown in the format of "Name: Amy" where Amy is the
     user's name. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_name">Name: <xliff:g id="name" example="Amy">%s</xliff:g></string>

   <!--
     Whipped cream topping for the order summary. It will be shown in the format of
     "Add whipped cream? true" or "Add whipped cream? false". [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_whipped_cream">Add Whipped Cream? <xliff:g id="addWhippedCream" example="true">%b</xliff:g></string>

   <!--
     Chocolate topping for the order summary. It will be shown in the format of
     "Add chocolate? true" or "Add chocolate? false". [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_chocolate">Add chocolate? <xliff:g id="addChocolate" example="true">%b</xliff:g></string>

   <!--
     Quantity of coffee cups for the order summary. It will be shown in the format of
     "Quantity: 2", where 2 is the number of cups ordered. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_quantity">Quantity: <xliff:g id="quantity" example="2">%d</xliff:g></string>

   <!--
     Total price for the order summary. It will be shown in the format of
     "Total: $10" where $10 is the price. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_price">Total: <xliff:g id="price" example="$10">%s</xliff:g></string>

   <!-- Thank you message for the order summary. [CHAR LIMIT=NONE] -->
   <string name="thank_you">Thank you!</string>

   <!--
     Subject line for the order summary email. It will be in the format of
     "Just Java order for Amy" where Amy is the user's name. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_email_subject">Just Java order for <xliff:g id="name" example="Amy">%s</xliff:g></string>
</resources>

(1)所有内容在 <resources …>... </resources> 内。
(2)字符串定义格式:

    <string name=“字符串名”>字符串</string>

(3)这里使用了 xliff 语句在字符串中添加变量,同时作为占位符表示这部分内容无需翻译,如

<!-- 指定 xliff 命名空间的 URL -->
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"
<!-- 在字符串中添加“姓名”字符串变量 -->
<string name="order_summary_name">Name: <xliff:g id="name" example="Amy">%s</xliff:g></string>
<!-- 在字符串中添加布尔类型变量 -->
<string name="order_summary_chocolate">Add chocolate? <xliff:g id="addChocolate" example="true">%b</xliff:g></string>

从上面的例子可以看出,xliff 语句起止于 <xliff:g ...>...</xliff:g>,中间内容依次为

  • 变量 ID,如 id="name"
  • 变量内容示例,如 example="Amy"
  • 变量格式说明符 (Format Specifiers),如 %s 指字符串,%b 指布尔类型,这篇文章列出了更多 Java 格式说明符。

(4)XML注释格式:

    <!-- … -->

写下具体的注释使代码易理解,对于字符串复用和翻译很有帮助。

  1. 在 strings.xml 定义所有字符串资源后,可在 XML 和 Java 中调用。

(1)XML 调用字符串,格式:@string/字符串名

<TextView
   android:id="@+id/quantity_text_view"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:paddingLeft="8dp"
   android:paddingRight="8dp"
   android:text="@string/initial_quantity_value"
   android:textColor="#000000"
   android:textSize="16sp" />

(2)Java 调用字符串,格式:R.string.字符串名

/**
* Create summary of the order..
*
* @param name            of the Customer
* @param price           of the order
* @param addWhippedCream is whether or not the user wants whipped cream topping
* @param addChocolate    is whether or not the user wants chocolate topping
* @return text summary
*/
private String createOrderSummary(String name, int price, boolean addWhippedCream, boolean addChocolate) {
   return getString(R.string.order_summary_name, name) + "\n" +
          getString(R.string.order_summary_whipped_cream, addWhippedCream) + "\n" +
          getString(R.string.order_summary_chocolate, addChocolate) + "\n" +
          getString(R.string.order_summary_quantity, quantity) + "\n" +
          getString(R.string.order_summary_price, NumberFormat.getCurrencyInstance().format(price)) + "\n" +
          getString(R.string.thank_you);
}
  1. Android App 有默认 (Default) 资源和替代 (Alternate) 资源,使 App 可面对不同的运行环境加载不同的资源,Google 搜索 "localization checklist" 进一步了解。支持多语言是本地化的其中一项工作,Google 搜索 "iso 639-1" 找到 Wikipedia 结果,了解全球语言缩写,如中文为 zh。
  2. 在 app→res 路径下新建 values-zh 目录并新建 strings.xml,翻译字符串为中文:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <!-- Title for the application. [CHAR LIMIT=12] -->
   <string name="app_name">Just Java</string>

   <!-- Hint text display in the empty field for the user's name [CHAR LIMIT=20] -->
   <string name="name">姓名</string>
   <string name="toppings">配料</string>
   <string name="whipped_cream">奶盖</string>
   <string name="chocolate">巧克力</string>
   <string name="quantity">数量</string>
   <string name="decrement">-</string>
   <string name="initial_quantity_value">1</string>
   <string name="increment">+</string>
   <string name="order">下单</string>

   <!--
     Name for the order summary. It will be shown in the format of "Name: Amy" where Amy is the
     user's name. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_name">姓名: <xliff:g id="name" example="Amy">%s</xliff:g></string>

   <!--
     Whipped cream topping for the order summary. It will be shown in the format of
     "Add whipped cream? true" or "Add whipped cream? false". [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_whipped_cream">需要添加奶盖? <xliff:g id="addWhippedCream" example="true">%b</xliff:g></string>

   <!--
     Chocolate topping for the order summary. It will be shown in the format of
     "Add chocolate? true" or "Add chocolate? false". [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_chocolate">需要添加巧克力? <xliff:g id="addChocolate" example="true">%b</xliff:g></string>

   <!--
     Quantity of coffee cups for the order summary. It will be shown in the format of
     "Quantity: 2", where 2 is the number of cups ordered. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_quantity">数量:<xliff:g id="quantity" example="2">%d</xliff:g></string>

   <!--
     Total price for the order summary. It will be shown in the format of
     "Total: $10" where $10 is the price. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_price">价格:<xliff:g id="price" example="$10">%s</xliff:g></string>

   <!-- Thank you message for the order summary. [CHAR LIMIT=NONE] -->
   <string name="thank_you">谢谢!</string>

   <!--
     Subject line for the order summary email. It will be in the format of
     "Just Java order for Amy" where Amy is the user's name. [CHAR LIMIT=NONE]
   -->
   <string name="order_summary_email_subject">Just Java 订单 <xliff:g id="name" example="Amy">%s</xliff:g></string>
</resources>

在 Android Studio 中左侧 Project 标签 Android 视图下找到 app→res→values→strings.xml 文件,右键菜单中找到并点击 "Open Editor",可打开对照翻译界面,如下图所示。

更多资源本地化的信息可到 Localizing with Resources | Android Developers 网站查看。

styles.xml
  1. 在 Android Studio 中左侧 Project 标签 Android 视图下 app→res→values→styles.xml 文件可统一定义 App 的主题以及 Views 的样式,减少代码冗余。
  2. Just Java App 中的 styles.xml 代码如下:
<resources>
   <!-- Base application theme. -->
   <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
       <!-- Customize your theme here. -->
       <item name="colorPrimary">@color/colorPrimary</item>
       <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
       <item name="colorAccent">@color/colorAccent</item>
   </style>

   <!-- Style for a header TextView. -->
   <style name="HeaderTextStyle" parent="Theme.AppCompat.Light.DarkActionBar">
       <!-- Customize your theme here. -->
       <item name="android:layout_width">wrap_content</item>
       <item name="android:layout_height">48dp</item>
       <item name="android:gravity">center_vertical</item>
       <item name="android:textAllCaps">true</item>
       <item name="android:textSize">15sp</item>
   </style>
</resources>

(1)所有内容在 <resources …>... </resources> 内。
(2)同一样式在 <style …>... </style> 内。
(3)属性定义格式:<item name=“属性名”>真实值</item>

  1. 在 styles.xml 定义样式资源后,可在 XML 中调用:
<TextView
   style="@style/HeaderTextStyle"
   android:text="@string/toppings" />

<TextView
   style="@style/HeaderTextStyle"
   android:text="@string/quantity" />

两个 TextView 相同处应用同一样式,不同处自行定义属性,减少代码冗余。

  1. 样式可应用于单个的 View,而主题的 style 是应用于某类活动或整个应用的,例如所有文字的颜色,应用栏或状态栏的颜色。如
   <!-- Base application theme. -->
   <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
       <!-- Customize your theme here. -->
       <item name="colorPrimary">@color/colorPrimary</item>
       <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
       <item name="colorAccent">@color/colorAccent</item>
   </style>

其中 parent="Theme.AppCompat.Light.DarkActionBar" 表示 App 主题通过 Appcompat 兼容使用了 Light.DarkActionBar 的主题。同时 AppTheme 在 AndroidManifest.xml 内引用,对于多屏幕应用,不同主题的 Activity 就在这个文件内指定。

if-else 语句
  1. 控制代码执行顺序称为控制流 (Control Flow),利用 if-else 语句可以使程序跳过部分代码。
  2. Just Java App 中的 if-else 语句如下:
/**
* This method is called when the + button is clicked.
*/
public void increment(View view) {
   if (quantity == 100) {
       // Show an error message as a toast
       Toast.makeText(this,
               "You cannot have more than 100 coffees!", Toast.LENGTH_SHORT).show();
       // Exit this method early because there's nothing left to do
       return;
   }
   quantity += 1;
   displayQuantity(quantity);
}

(1)当满足 if 小括号内的条件时,执行大括号内的代码,否则执行 else 大括号内的代码。
(2)当 else 无需任何操作时可删去。
(3)利用 return; 提前结束 method。
(4)运算符 += 可精简代码。
(5)用 toast 告知用户错误信息或提示,以防用户误以为 App 故障或停止运行。Google 搜索 "toast android" 进一步了解。

Intent
  1. 利用 Android 框架 Intent 请求其它 App 组件完成动作,使 App 能使用其他 App 的功能,避免重复开发,如相机、地图、浏览器、邮件等。Google 搜索 "common intents" 进一步了解。
  2. Intent 就像传球,无需指定某一个 App 接球,只要设备中有 App 响应,把球接住即可。
  3. Intent 的内容通常有常规动作 (Action)、动作的数据 (Data),还有 Category、Component、Extra。
  4. Just Java App 中的 Intent 代码如下:
Intent intent = new Intent(Intent.ACTION_SENDTO);
// only email apps should handle this
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.order_summary_email_subject, name));
intent.putExtra(Intent.EXTRA_TEXT, createOrderSummary(name, price, hasWhippedCream, hasChocolate));
if (intent.resolveActivity(getPackageManager()) != null) {
   startActivity(intent);
}

(1)Intent的常规动作 (Aciton): ACTION_SENDTO,常量(全大写、值不变)。
(2)Intent 的动作数据 (Data): Uri.parse(“mailto:”),有标准格式,Uniform Resource Identifier。
(3)Intent 的额外数据 (Extra): EXTRA_SUBJECT、EXTRA_TEXT 分别设置邮件主题和内容的文本。
(4)if 语句判断设备中是否有 App 能响应 Intent,防止 App 崩溃。

Intent 的内容会在接下来课程中详细介绍。至此 Just Java App 的开发就告一段落了,现阶段这个咖啡订购 App 实现的功能有

  1. 输入订购人姓名;
  2. 选择订购数量,范围为 1~100;
  3. 选择是否添加奶盖和巧克力;
  4. 将订购信息(包含价格)发送到邮箱。

第一部分《布局和交互》的课程完成了,同时也迎来了入门课程的第三个实战项目:AUdacityQuiz 小测验应用,它应用了除 Intent 外已学的所有知识点,

以下是在 coding 过程中发现的几个关键点:

  1. 在 AndroidManifest.xml 内的 MainActivity 添加 android:windowSoftInputMode="stateHidden" 使 App 启动时输入法不会自动弹出。
  2. 为了防止手机在旋转后 RadioButton 的状态丢失,override 了 onSaveInstanceState 和 onRestoreInstanceState 用于保存 RadioButton 的状态。
// Save the isQuestionTwoRight and isQuestionTwoRight variable state
// When phone rotate to the landscape mode or portrait mode
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    // Save UI state changes to the savedInstanceState.
    // This bundle will be passed to onCreate if the process is killed and restarted.
    savedInstanceState.putBoolean("isQuestionTwoRight", isQuestionTwoRight);
    savedInstanceState.putBoolean("isQuestionThreeRight", isQuestionThreeRight);
}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    // Restore UI state from the savedInstanceState.
    // This bundle has also been passed to onCreate.
    isQuestionTwoRight = savedInstanceState.getBoolean("isQuestionTwoRight");
    isQuestionThreeRight = savedInstanceState.getBoolean("isQuestionThreeRight");
}
  1. 利用 TextView 属性使两行内容的 Toast 文字居中显示。
Toast toast = Toast.makeText(this, getString(R.string.toast_line_one, result) + "\n" + getString(R.string.toast_line_two, score), Toast.LENGTH_SHORT);
// Center each of the two lines Toast texts
TextView v = toast.getView().findViewById(android.R.id.message);
if (v != null) {
    v.setGravity(Gravity.CENTER);
}
toast.show();
  1. 在 ImageView 中通过两条指令使图片完整显示。
android:adjustViewBounds="true"
android:scaleType="centerInside"
  1. 通过 if/else 语句添加了一条错误提示的 Toast。

这次项目导师还给出了一些很棒的建议,例如定义 style 时应该注意的一些问题:

  1. 所有 style 都应该有一个 parent;
  2. 给 style 命名时应该遵循 parent 的命名惯性;
  3. 最好让自定义 style 继承自 AppCompat 而不是系统的 style,以确保能向后兼容性。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,016评论 25 707
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,389评论 0 17
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,421评论 2 45
  • 140. Word Break II 今天开始恢复做难题,算了一下还有大概80道题这样,每天保质5道题,20道总结...
    健时总向乱中忙阅读 156评论 0 0
  • 见过我的人都说,我比同龄人成熟,共事的同事都说,我成熟稳重,做事靠谱,朋友都说,我略显呆板,想法灰暗,镜子对我说,...
    dreamingyou阅读 265评论 0 0