20189230楊 2018-2019-2 《移動平臺開發實踐》第6周學習總結

學習《Java和Android開發學習指南(第二版)》第2三、2四、2五、26章——

第23章 Android簡介
1.Android向後兼容,針對較早的版本編寫的應用程序,總可以在新的版本上運行。
2.4種Android應用程序組件:
活動(Activity):包含用戶交互組件的一個窗口。
服務(Service):在後臺長時間運行的操做。
廣播接收者(Broadcast receiver):一個監聽器,負責對系統或應用程序聲明做出響應。
內容提供者(Content provider):管理要和其餘應用程序分享的一組數據的一個組件。
3.每一個應用程序都必須有一個清單(manifest),描述該應用程序。清單以XML文件的形式給出,其中包含的內容有:
運行該應用程序所需的最小API Level。
應用程序的名稱。這個名稱將會顯示在設備上。
當用戶在其手機或平板電腦的主屏幕上觸碰該應用程序的圖標時,將會打開的第一個活動(窗口)。
是否容許從其餘的應用程序調用你的應用程序組件。
對於在目標設備上安裝的應用程序,用戶必須保證一組什麼樣的許可。若是用戶不能保證全部必須的許可,將不會安裝該應用程序。java

第24章 初識Android
24.4 應用程序結構
1.Project窗口中有兩個主要的節點,app和Gradle Scripts。App節點包含了應用程序中全部的組件。Gradle Scripts節點包含了Gradle構件腳本,供Android Studio構建你的項目。
app節點下面有以下的3個節點:
Manifests。包含了一個AndroidManifest.xml文件,它描述了應用程序。
java。包含了全部的Java應用程序和測試類。
res。包含了資源文件。在這個目錄下還有一些目錄:
drawable(包含了用於各類屏幕分辨率的圖像),layout(包含了佈局文件)和menu(包含了菜單文件),mipmap(包含了用於各類屏幕分辨率的app圖標),還有values(包含了字符串和其餘值)。
2.R類
R類是一個名爲R的通用的Java類,能夠在項目的app/build/generated/source目錄下找到。R包含了嵌套的類,該類反過來包含了全部資源ID。每次添加、修改或刪除資源的時候,都會從新生成R。例如,若是你向res/drawable目錄添加了一個名爲logo.png的文件,Android Studio將在drawable類下面生成一個名爲logo的文件。R的做用是讓你可以引用代碼中的一個資源。
24.4.1 Android清單
1.建立一個新項目241
(1)主函數android

package com.example.yangxiaopang.a241;

        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

(2)清單文件git

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

(3)項目運行結果
打印出Hello World!
api

第25章活動
25.1 活動的生命週期
數組

25.2 ActivityDemo示例
1.代碼清單25.1 ActivityDemo的清單android-studio

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitydemo" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.activitydemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2.代碼清單25.2 ActivityDemo的MainActivity類安全

package com.example.activitydemo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("lifecycle", "onCreate");
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("lifecycle", "onStart");
    }

    @Override
    public void onRestart() {
        super.onRestart();
        Log.d("lifecycle", "onRestart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("lifecycle", "onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("lifecycle", "onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("lifecycle", "onStop");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("lifecycle", "onDestroy");
    }
}


25.5 啓動另外一個活動
1.代碼清單25.3 SecondActivityDemo的清單bash

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.secondactivitydemo" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.secondactivitydemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.secondactivitydemo.SecondActivity"
            android:label="@string/title_activity_second" >
        </activity>
    </application>

</manifest>

2.代碼清單25.4 activity_main.xml文件多線程

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/first_screen" />

</RelativeLayout>

3.代碼清單25.5 activity_second.xml文件

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".SecondActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

4.代碼清單25.6 MainActivity類

package com.example.secondactivitydemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;

public class MainActivity extends Activity implements
        OnTouchListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = (TextView) findViewById(R.id.textView1);
        tv.setOnTouchListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it 
        // is present. 
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
        Intent intent = new Intent(this, SecondActivity.class);
        intent.putExtra("message", "Message from First Screen");
        startActivity(intent);
        return true;
    }
}

5.代碼清單25.7 SecondActivity類

package com.example.secondactivitydemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Intent intent = getIntent();
        String message = intent.getStringExtra("message");
        ((TextView) findViewById(R.id.textView1)).setText(message);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_second, menu);
        return true;
    }
}

第26章UI組件
26.1 概覽
1.微件和佈局,都在android.view.View類中實現。
26.2 使用Android Studio UI工具
1.使用UI工具所作的事情,都會反映到佈局文件中,以XML元素的形式體現出來。要查看你生成了什麼,單擊UI工具底部的XML視圖便可。
26.3 使用基本組件
1.代碼清單26.1 BasicComponents項目的清單文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.basiccomponents"
    android:versionCode="1"
    android:versionName="1.0">

   <!--uses-sdk android:targetSdkVersion="17" /-->

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.basiccomponents.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category
                    android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

2.代碼清單26.2 res/values下的strings.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">BasicComponents</string>
    <string name="action_settings">Settings</string>
    <string name="prompt_email">Email</string>
    <string name="prompt_password">Password</string>
    <string name="action_sign_in"><b>Sign in</b></string>
</resources>

3.代碼清單26.3 佈局文件

<LinearLayout 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"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="120dp"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/prompt_email"
        android:inputType="textEmailAddress"
        android:maxLines="1"
        android:singleLine="true" />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/prompt_password"
        android:imeActionId="@+id/login"
        android:imeOptions="actionUnspecified"
        android:inputType="textPassword"
        android:maxLines="1"
        android:singleLine="true" />

    <Button
        android:id="@+id/sign_in_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginTop="16dp"
        android:paddingLeft="32dp"
        android:paddingRight="32dp"
        android:text="@string/action_sign_in" />

</LinearLayout>

4.代碼清單26.4 BasicComponents項目的MainActivity類

package com.example.basiccomponents;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it 
        // is present. 
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
}

26.5 通知
1.代碼清單26.5 NotificationDemo的主活動的佈局文件

<LinearLayout 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"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="120dp"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/prompt_email"
        android:inputType="textEmailAddress"
        android:maxLines="1"
        android:singleLine="true" />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/prompt_password"
        android:imeActionId="@+id/login"
        android:imeOptions="actionUnspecified"
        android:inputType="textPassword"
        android:maxLines="1"
        android:singleLine="true" />

    <Button
        android:id="@+id/sign_in_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginTop="16dp"
        android:paddingLeft="32dp"
        android:paddingRight="32dp"
        android:text="@string/action_sign_in" />

</LinearLayout>

2.代碼清單26.6 主活動類

package com.example.notificationdemo;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {
    int notificationId = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void setNotification(View view) {
        Intent intent = new Intent(this, SecondActivity.class);
        PendingIntent pendingIntent =
                PendingIntent.getActivity(this, 0, intent, 0);

        Notification notification  = new Notification.Builder(this)
                .setContentTitle("New notification")
                .setContentText("You've got a notification!")
                .setSmallIcon(android.R.drawable.star_on)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .addAction(android.R.drawable.ic_menu_gallery,
                        "Open", pendingIntent)
                .build();
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(
                        NOTIFICATION_SERVICE);
        notificationManager.notify(notificationId, notification);
    }

    public void clearNotification(View view) {
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(
                        NOTIFICATION_SERVICE);
        notificationManager.cancel(notificationId);
    }
}

單擊Set Notification按鈕,通知圖標(一個橙色的星)將會出如今狀態欄上:

將狀態欄向屏幕的右下方拖動以打開通知繪製區:

觸碰通知啓動SecondActivity:

教材學習中的問題和解決過程

  • 問題1:本週出現的問題主要是Android Studio下載安裝和使用的問題。
  • 問題解決方案1:把Android Studio項目從C盤移植到了D盤,解決了SDK包和模擬器所佔內存空間太大,致使項目沒法運行的問題。

代碼調試中的問題和解決過程

  • 問題1:從配套程序示例中直接導入的項目屢次報錯,沒法運行。
  • 問題1解決方案:
    (1)Error:Unsupported method: BaseConfig.getApplicationIdSuffix().
    A.修改項目的build.gradle文件,找到dependencies,修改classpath
    classpath 'com.android.tools.build:gradle:1.0.0'
    改爲:
    classpath 'com.android.tools.build:gradle:3.2.0';
    B.上一步修改了build.gradle中的版本以後,gradle-wrapper.properties文件中的gradle的版本也須要修改,
    直接修改:distributionUrl
    distributionUrl=https://services.gradle.org/distributions/gradle-4.6-all.zip
    (2)修改後運行又報錯:
    Configuration ‘compile’ is obsolete and has been replaced with ‘implementation’ and ‘api’.
    It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
    A.修改build gradle:compile fileTree(dir: 'libs', include: ['*.jar'])爲implementation fileTree(dir: 'libs', include: ['*.jar'])便可。
  • 問題2:本週課堂做業在上傳碼雲的時候老是push報錯
  • 問題2解決方案:在app處git bash here上傳src文件夾的時候,如不手動更改src文件夾名稱,就會在pull和push過程當中將先前的項目自動覆蓋。

上週錯題總結

1.Assume that you have an InputStream whose next bytes are XYZABC. What is the result of
calling the following method on the stream, using a count value of 3?
假若有一個InputStream,接下來的內容是XYZABC,下面代碼中假如count
爲3,下面代碼執行結果是?
public static String pullBytes(InputStream is, int count) throws IOException
{
is.mark(count);
final StringBuilder sb = new StringBuilder();
for(int i=0; i<count; i++)
sb.append((char)is.read());
is.reset();
is.skip(1);
sb.append((char)is.read());
return sb.toString();
}
A .It will return a String value of XYZ.
B .It will return a String value of XYZA.
C .It will return a String value of XYZX.
D .It will return a String value of XYZB.
E .It will return a String value of XYZY.
F .The code does not compile.
G .The code compiles but throws an exception at runtime.
H .The result cannot be determined with the information given.
正確答案: H 個人答案: A
並不是全部java.io流都支持mark()操做;所以,若是不在流上調用mark-supported(),則在運行時以前結果是未知的。若是流確實支持mark()操做,那麼結果將是xyzy,由於reset()操做將流放回調用mark()以前的位置,skip(1)將跳過x,e將正確。若是流不支持mark()操做,則可能會引起運行時異常,而且g是正確的。由於不知道輸入流是否支持mark()操做,因此h是惟一正確的選擇。

2.What is the value of name after an instance of Eagle is serialized and then deserialized?
Eagle的一個實例通過serialized 和 deserialized後,name的值是?
public class Bird implements Serializable {
protected transient String name = "Bridget";
public void setName(String name) { this.name = name; }
public String getName() { return name; }
public Bird() {
this.name = "Matt";
}
}
public class Eagle extends Bird implements Serializable {
{ this.name = "Janette"; }
public Eagle() {
this.name = "Daniel";
}
}
A .Bridget
B .Matt
C .Janette
D .Daniel
E .null
F .The code does not compile.
G .The code compiles but throws an exception at runtime.
H .The value may not be known until runtime.
正確答案: E 個人答案: B
首先,雖然bird類實現了serializable,但它沒有定義建議但不須要的非靜態serial version uid變量;所以它編譯時沒有問題,而f是不正確的。代碼也能夠毫無問題地運行,所以g是不正確的。這裏的關鍵是,Java將在反序列化期間調用第一個非序列化的無參數父類的構造函數,跳過任何構造函數和介於其間的序列化類的默認初始化,包括EGLE和BED自己。所以,object()是第一個被調用的構造函數。跳過全部默認初始化,所以a、b、c和d都不正確。因爲名稱被標記爲瞬態,所以反序列化的值爲空,而且e是正確的。h也不正確,由於調用方不能用setname()更改name的序列化值,由於name被標記爲transien。

3.Assuming the following class has proper public getter/setter methods for all of its private fields, which of the following fields will always be null after an instance of the class is
serialized and then deserialized? (Choose all that apply.)
加入下面的類的private成員都有合適的public getter/setter,類的實例serialized and 和 deserialized後哪些成員會是null?
public class Zebra implements Serializable {
private static final long serialUID = 1L;
private transient String name = "George";
private static String birthPlace = "Africa";
private transient Integer age;
private java.util.List friends = new java.util.ArrayList<>();
private Object tail = null;
{ age = 10;}
public Zebra() {
this.name = "Sophia";}
}
}
A .name
B .tail
C .age
D .friends
E .birthPlace
F .The code does not compile.
G .The code compiles but throws an exception at runtime.
正確答案: A C 個人答案: B D
代碼編譯和運行時沒有問題,所以f和g是不正確的。請注意,serial uid與serial version uid不一樣,儘管建議使用serial version uid,但不須要使用,所以不會形成任何編譯問題。請注意,序列化過程不會使用seria luid進行版本控制。名稱變量和年齡變量都是暫時的,這意味着它們的值在序列化時不會被保存。反序列化後,將跳過默認初始化和構造函數,它們都將爲空;所以a和c是正確的。B不正確,由於它不是暫時的,而且能夠由調用方在序列化以前設置。d也不正確,由於序列化的空數組與空指針不一樣。即便這些非瞬態字段能夠設置爲空,但在反序列化後它們也不能保證爲空。E不正確,由於靜態值不會被序列化;反序列化後,它將在類上可用。

5.Which values when inserted into the blank would allow the code to compile? (Choose all
that apply.)
插入哪些代碼可讓下面的代碼正確編譯?
1: Console console = System.console();
2: String color = console.readLine("What is your favorite color? ");
3: console._("Your favorite color is "+color);
A .print
B .printf
C .println
D .format
E .writer().println
F .out
正確答案: B D E 個人答案: A C E
控制檯定義兩個輸出方法,format()和printf(),它們是相同的在函數中,因此b和d是正確的。a、c和f都不正確,由於在控制檯類中沒有定義具備該名稱的此類方法。還可使用writer()方法訪問控制檯的printwriter對象,所以e是正確的。
11.Suppose that the file c:\book\java exists. Which of the following lines of code creates an
object that represents the file? (Choose all that apply.)
A .new File("c:\book\java");
B .new File("c:\book\java");
C .new File("c:/book/java");
D .new File("c://book//java");
E .None of the above
正確答案: B C 個人答案: A C
選項B是正確的,由於Java須要用另外一個反斜槓來轉義反斜槓。選項C也是正確的,由於Java將在使用路徑時將斜槓轉換爲右斜槓。
21.若是有如下代碼片斷:
...
public
_________ void add(Object o) {
if(next == list.length) {
list = Arrays.copyOf(list, list.length * 2);
}
list[next++] = o;
}
...
爲了確保add()在多線程訪問下的線程安全,應該加上()關鍵字。
A .abstract
B .synchronized
C .static
D .volatile
正確答案: B 個人答案: D
要點:synchronized和volatile的使用方法以及區別——
一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾以後,那麼就具有了兩層語義:
1)保證了不一樣線程對這個變量進行操做時的可見性,即一個線程修改了某個變量的值,這新值對其餘線程來講是
當即可見的。
2)禁止進行指令重排序。
volatile本質是在告訴jvm當前變量在寄存器(工做內存)中的值是不肯定的,須要從主存中讀取;
synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其餘線程被阻塞住。
1.volatile僅能使用在變量級別;
synchronized則可使用在變量、方法、和類級別的
2.volatile僅能實現變量的修改可見性,並不能保證原子性;
synchronized則能夠保證變量的修改可見性和原子性
3.volatile不會形成線程的阻塞;
synchronized可能會形成線程的阻塞。
4.volatile標記的變量不會被編譯器優化;
synchronized標記的變量能夠被編譯器優化

[代碼託管]

https://gitee.com/EvelynYang/sixth_week_homework

statistics.sh腳本運行結果的截圖

新建AndroidProjects文件夾運行腳本,以前都是在IdeaProjects文件夾裏運行。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 200/200 2/2 20/20
第二週 300/500 1/3 18/38
第三週 500/1000 1/4 38/76
第四周 1000/2000 1/5 20/96
第五週 1000/3000 1/6 25/121
第六週 1000/4000 1/7 25/146

參考資料

相關文章
相關標籤/搜索