facebook廣告





123

2017年1月28日 星期六

Java 入門指南 - 建構子

Java 入門指南 - 建構子

Java 中建立物件 (object) 需要建構子 (constructor) ,如果類別 (class) 沒有定義建構子,編譯器 (compiler) 就會提供一個預設的建構子 (default constructor)




我們現在要來詳細討論建構子的作用與功能,建構子的主要目的在於建立物件的過程中,也就是使用 new 關鍵字 (keyword) 的時候,程式 (program) 建立物件所執行的工作,這些工作通常就是初始化物件的屬性 (field) 。


如果類別沒有定義建構子,編譯器會提供預設預購子,預設建構子為沒有參數 (parameter) 的版本
public Encrypt() {}


須注意,如果我們有在類別中定義建構子,編譯器便不會提供沒有參數版本的預設建構子。建構子可以依需求而有不同的參數版本,例如 Encrypt 中我們需要這些屬性
char[] cArray;
int a;
int b;
int n;
char c;
int diff;


其中 a 、 b 、 n 、 c 、 diff ,我們需要提供這五個屬性值,然後呼叫 setArray() 計算出 cArray 的值
public Encrypt(int a, int b, int n, char c, int dif) {
    this.a = a;
    this.b = b;
    this.n = n;
    this.c = c;
    this.diff = dif;
    setArray();
}


當然,有些屬性值也可以用預設的,這就是形成不同參數版本的建構子
public Encrypt(int a, int b) {
    this(a, b, 26, 'a', 97);
}


這是利用 this 呼叫最多參數版本的建構子, a 、 b 為此建構子所需要提供的參數,其餘三個 n 、 c 、 diff ,我們直接以字面常數 (literal) 代入預設值, 也就是 n 為 26 , c 為 'a' , diff 為 97 。


可是 Encrypt 不是要 a 、 b 都為 0 到 9 隨機整數的隨機值嗎?我們仍得在 EncryptDemo 中進行設定嗎?不,不需要,我們可以設計沒有參數版本的建構子
public Encrypt() {
    int ta = 0;
    int tb = 0;
         
    while (ta % 2 == 0) {
        ta = (int) (Math.random() * 10);
        tb = (int) (Math.random() * 10);
    }
         
    this.a = ta;
    this.b = tb;
    this.n = 26;
    this.c = 'a';
    this.diff = 97;
    setArray();
}


這裡,屬性設定的部份也可以這樣寫
a = ta;
b = tb;
n = 26;
c = 'a';
diff = 97;
setArray();


我們並沒有用到與屬性名稱相同的區域變數 (local variable) ,所以可以直接以屬性名稱設定數性質。我們仍使用 this 的原因很簡單,就是既然前兩個建構子都有用到 this ,我們這裡維持一致性,所以也用 this 來設定屬性。


完整的 Encrypt 如下
?
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class Encrypt {
    // 屬性
    char[] cArray = new char[26];
    int a;
    int b;
    int n;   
    char c; 
    int diff;
     
    // 建構子
    public Encrypt(int a, int b, int n, char c, int dif) {
        this.a = a;
        this.b = b;
        this.n = n;
        this.c = c;
        this.diff = dif;
        setArray();
    }
 
    public Encrypt(int a, int b) {
        this(a, b, 26, 'a', 97);
    }
 
    public Encrypt() {
        int ta = 0;
        int tb = 0;
         
        while (ta % 2 == 0) {
            ta = (int) (Math.random() * 10);
            tb = (int) (Math.random() * 10);
        }
         
        this.a = ta;
        this.b = tb;
        this.n = 26;
        this.c = 'a';
        this.diff = 97;
        setArray();
    }   
     
    // setter 方法
    public void setArray() {
        int i, y, x, m;
        char r;
         
        x = c;
        for (i = 0; i < n; i++) {
            y = x * a + b;
            m = y % n;
            r = (char) (m + diff);
            cArray[i] = r;
            x++;
        }       
    }
}
 
/* 《程式語言教學誌》的範例程式
    檔名:Encrypt.java
    功能:示範 Java 程式
    作者:張凱慶
    時間:西元 2011 年 4 月 */


然後修改 EncryptDemo 進行測試
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 測試 Encrypt 的類別
public class EncryptDemo {
    public static void main(String[] args) {
        System.out.println();
        for (int i = 0; i < 16; i++) {
            Encrypt t = new Encrypt();
            System.out.println(t.cArray);
        }
        System.out.println();
    }
}
 
/* 《程式語言教學誌》的範例程式
    檔名:EncryptDemo.java
    功能:示範 Java 程式
    作者:張凱慶
    時間:西元 2011 年 4 月 */


記得 Encrypt 與 EncryptDemo 都修改過,因此執行前都要先進行編譯,如下



這裡,我們在 EncryptDemo 中直接用句點運算子存取屬性 cArray ,其實不一個好習慣,因為如此物件的資料就曝光在世人面前,任何人都可以透過句點運算子存取,甚至更改屬性值,造成難以彌補的後果,從而失去資訊隱藏 (information hiding) 的意義。


因此,我們應該將屬性設成 private ,然後以 getter 與 setter 進行操作哩!


中英文術語對照
物件object
建構子constructor
類別class
編譯器compiler
建構子default constructor
關鍵字keyword
程式program
屬性field
參數parameter
字面常數literal
區域變數local variable
資訊隱藏information hiding

Fragment和FragmentActivity的使用方法

https://my.oschina.net/zhouyuan/blog/152496
认识:首先我们知道Fragment是我们在单个Activity上要切换多个UI界面,显示不同内容。模块化这些UI面板以便提供给其他Acitivity使用便利。同时我们显示的Fragment也会受到当前的这个Acitivity生命周期影响。(而平常的Fragment有其自己的生命周期)
一、使用方法:
1、创建一个或者多个你需要的Fragment类,其实就是类似activity一样,也有OnCreate()等回调函数。
2、如果要让当前的程序也就是Activity使用Fragment的话,需要把Acitivity中相关的回调函数内容搬过去。you might simply move code from your activity's callback methods into the respective callback methods of your fragment
一般地,我们需要以下回调函数:
onCreate() onCreateView() onPause()
除了以上3个我们基本上都要用到的回调函数方法,那么我们写得Fragment中还有其他: Handling the Fragment Lifecycle
二、关于继承Fragment类
除了基本的Fragment类,我们还可以继承的有:
DialogFragment ListFragment PreferenceFragment
三、添加用户界面
我们再 onCreateView() 里面处理我们的Fragment要显示的界面,返回的是一个View,这个View其实就是我们定义这个Fragment的Layout的root项(最外的、最大的那个哦!)。
从XML布局中生成View我们用LayoutInflater这个助手类提供的方法。
文解决我这两天的问题,故转载:原文Android Tabhost with FragmentActivity
2012-05-07 更新)接續Android TabHost中切換Activity記錄了使用ActivityGroup達到在TabHost中切換Activity的方法,也在Android Screen Orientation Event螢幕方向處理+Acitivity Liftcycle記錄了當螢幕方向改變時的處理,這篇小蛙繼續記錄用FragmentActivity取代ActivityGroup,透過FragmentActivity內建的BackStack來管理倒退歷程。
MainTabActivity.java : 主要的Tabhost Activity。
[java] view plaincopy public class MainTabActivity extends Activity {
private TabHost mHost;
// 在Activity中使用Tabhost必須要有LocalActivityManager物件來設定
LocalActivityManager lam;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// main layout採用預設的Tabhost
mHost = (TabHost) findViewById(android.R.id.tabhost);
    lam = new LocalActivityManager(MainTabActivity.this, false);  
    lam.dispatchCreate(savedInstanceState);  

    mHost.setup(lam);  
    mHost.addTab(mHost.newTabSpec("Tab1").setIndicator("Tab1").setContent(new Intent(MainTabActivity.this, FragmentActivity1.class)));  
    mHost.addTab(mHost.newTabSpec("Tab2").setIndicator("Tab2").setContent(new Intent(MainTabActivity.this, FragmentActivity2.class)));  
}  
@Override  
protected void onPause() {  
    // 漏掉這行一定出錯  
    lam.dispatchPause(isFinishing());  
    super.onPause();  
}  
@Override  
protected void onResume() {  
    // 漏掉這行一定出錯  
    lam.dispatchResume();  
    super.onResume();  
}  
}
FragmentActivity1.java : 第一個Tab中用來管理Fragment的FragmentActivity。(2012-05-07更新)經由Jay留言後,小蛙詳細測了一下,發現FragmentActivity主畫面中的Button是沒辦法消失的(因為FragmentActivity的目的關係),因此改成這樣,讓FragmentActivity純粹當成容器,主要的內容還是以Fragment為主。(這個方法不是唯一,但是一個可行的方法,應該也有更好的做法!)
[java] view plaincopy public class FragmentActivity1 extends FragmentActivity {
public static FragmentManager fm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_activity_1);
fm = getSupportFragmentManager();
// 只當容器,主要內容已Fragment呈現
initFragment(new Fragment1());
}
// 切換Fragment
public static void changeFragment(Fragment f){
changeFragment(f, false);
}
// 初始化Fragment(FragmentActivity中呼叫)
public static void initFragment(Fragment f){
changeFragment(f, true);
}
private static void changeFragment(Fragment f, boolean init){
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simple_fragment, f);
if(!init)
ft.addToBackStack(null);
ft.commit();
}
}
Fragment1.java : 真正使用到的Fragment。
[java] view plaincopy public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_1, container, false);
Button tv = (Button)v.findViewById(R.id.button2);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 直接呼叫FragmentActivity1的靜態方法來做切換
FragmentActivity1.changeFragment(new Fragment2());
}
});
return v;
}
}
fragment_acitivity_1.xml : FragmentActivity layout。(2012-05-07修改) FragmentActivity只用來當容器,而不真正呈現內容(僅把Fragment內容載入)。
[html] view plaincopy <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:id="@+id/simple_fragment">
</LinearLayout>
fragment1.xml:Fragment layout,FragmentActivity載入的真正內容。
[html] view plaincopy <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" />
</LinearLayout>
最後別忘了在AndroidManifest.xml中加入android:configChanges="orientation"設定。這樣就成功的使用在Activity中使用Tabhost並且透過FragmentActivity來管理Fragment囉!
下面讲讲为啥要用Fragment: 首先,Fragment可以兼容手机和平板,最大减少针对不同平台的工作量。 其次,Fragment可以向下兼容(通过android官方的Support Package),在2.x平台上没有任何问题。 最重要的是,Fragment实质上是一种可以包含控制代码的视图模块,可以非常方便的进行组合。
[另外,如果大家现在去看TabActivity的官方文档,会发现此类已被标记为deprecated,建议使用Fragment代替]
废话少说,给大家展示两个项目,都是github上面开源的。 1.水平分页指示器,google+中有用到这种效果,现已成为android4.0标配。 这个项目只是实现了分页指示。谷歌的Support Package自己内置了一套水平滑动的方案,非常实用,基于Fragment实现。 在此输入图片描述 2.给大家一个完整的使用Fragment的项目案例。 这个项目做的好像是一个电视节目提醒之类的东西,运行截图如下: 在此输入图片描述
下面附上这两个开源项目的地址: 1.水平分页指示器 https://github.com/tisa007/Android-ViewPagerIndicator/zipball/master 2.使用Fragment的项目案例 https://github.com/UweTrottmann/SeriesGuide

ActionBar

ActionBar

Android的ActionBar是一個很難搞的東西,除了版本的問題之外還有實體按鈕的MENU問題,導致我在摸索的時候花了很長的時間才了解問題的所在。



上面第一張圖的3,在ActionBar中稱為Overflow,請參考第二張圖,這個Overflow也是問題的所在,因為在我寫好的Android程式執行之後完全找不到Overflow,問題的原因經過不斷的在網路上爬文找的答案是,如果你的機器上有MENU的按鈕則不會顯示Overflow,如果沒有才會顯示,因此Overflow只是給沒有MENU的機器所使用的。

在預設的Android中按MENU只會跳出Settings的MENU選項而已,這邊舉個例子增加MENU的選項,在res/menu目錄中找到你主要Activity的xml檔,以我的檔案為例,我的xml檔案名稱叫做main.xm,參考下面的範例:

main.xml
<menu 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" tools:context="com.example.golden.lab.MainActivity" > <item android:id="@+id/action_help" android:title="@string/action_help" android:icon="@drawable/ic_action_help" android:showAsAction="ifRoom" /> <item android:id="@+id/action_settings" android:orderInCategory="100" android:title="@string/action_settings" android:showAsAction="always" /> </menu>
上面的範例main.xml新增了一個help的MENU,android:id是物件的名稱,為了撰寫程式所使用,在後面會提到。android:title是指在MENU中顯示的文字,因為有@string因此會參考到res/values/strings.xml,必須在裡面新增help文字。android:icon是提供MENU圖案的功能,不過我目前還是沒有成功就是了,Android有提供Action Bar Icon Pack提供使用者下載或是使用者也可以加入自己想要的icon圖案,只要將icon圖案加入到res/drawable每個解析度底下就可以使用了。最後android:showAsAction的功能有一些參數我列在下面:

  • ifRoom - 如果有ActionBar有空間的話會就會顯示item出來
  • withText - 顯示item的文字,可以搭配|來使用,例如ifRoom|withText
  • never - 不會顯示在ActionBar上面
  • always - 總是顯示在ActionBar上面,但官方的文件說不建議這樣做
現在已經在MENU中新增了help選項了,但是需要在Activity主程式中加入,但是因為我使用的Eclipse已經幫我做到這一點了,我就不需要再做這個動作了。

MainActivity.java
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }
不過網路上有不少人這樣寫:
public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; }
這兩者的寫法都可以產生MENU,要撰寫目錄的事件方法必須在onCreateOptionsMenu裡撰寫,MenuInflater是用來定義MENU用的,MenuInflater.inflate用來指定是哪個MENU。

最後我們將menu中的action_setting的android:showAsAction屬性改成never,再將action_help的android:showAsAction屬性改成always,使得action_help的icon能夠出現。

<menu 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" tools:context="com.example.golden.lab.MainActivity" > <item android:id="@+id/action_help" android:title="@string/action_help" android:icon="@drawable/ic_action_help" android:showAsAction="always" /> <item android:id="@+id/action_settings" android:orderInCategory="100" android:title="@string/action_settings" android:showAsAction="never" /> </menu>




新增Item事件


目前已經完成新增MENU的項目了,但是點下所新增的help項目沒有任何的反應,因此接下來的動作必須新增help的事件動作。要新增item的事件動作必須在onOptionsItemSelected裡進行撰寫,設定按下help跳到另一個Activity。

MainActivity.java public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.action_help: Help(); return true; case R.id.action_settings: return true; default: return super.onOptionsItemSelected(item); } } private void Help() { Intent intent = new Intent(this,Help.class); startActivity(intent); } }
在上面的onOptionsItemSelected函數中可以看到使用switch來判斷是按下哪一個item,如果是按下help則會呼叫Help()方法,Help()方法中使用Intent切換到另一個Activity,因此還必須新增一個help.java的Activity。

MainActivity.java畫面
按下help到help.java的畫面






返回Activity畫面


雖然上圖help的Activity有一個左邊的箭頭可以返回到main的Activity,但是實際上在我的手機上面沒有,因此接下來的動作要在help的Activity加上返回的動作。 public class Help extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_help); ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.help, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.action_settings: return true; case android.R.id.home: NavUtils.navigateUpFromSameTask(this); return true; default: return super.onOptionsItemSelected(item); } } }
使用actionBar.setDisplayHomeAsUpEnabled就可以讓ActionBar顯示返回的箭頭,但是不會返回到main的Activity,因此還必須在onOptionsItemSelected函數中加入android.R.id.home進行判斷,且利用NavUtils.navigateUpFromSameTask返回到主頁。 




更換ActionBar icon和隱藏ActionBar


要更換ActionBar的icon很簡單,只需要一段文字actionBar.setIcon,指定好icon圖案就可以,接下來修改help的Activity來更換icon圖案,下面是範例。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_help); ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setIcon(R.drawable.help); }
從上面的圖可以看到icon已經被我換成自己所設定的了,除了主程式裡面可以更換icon還可以利用AndroidManifest.xml來進行設定,AndroidManifest.xml當中的<activity></activity>可以設定icon和ActionBar的標題,每一個<activity></activity>代表的是不同的Activity,因此可以根據不同的Activity畫面設定不同的icon,下面是範例:
<activity android:name=".MainActivity" android:label="Android" android:logo="@drawable/help" > </activity> android:label是設定ActionBar的標題,android:logo是設定ActionBar的icon ,如果要統一設定每個Activity的ActionBar的標題和icon在AndroidManifest.xml的<application></application>進行設定,請參考下面的範例:
<application android:allowBackup="true" android:icon="@drawable/help" android:label="@string/app_name" android:theme="@style/AppTheme" > </application> 設定每個Activity的icon和標題分別是android:icon和android:label,很簡單吧!!
  
ActionBar還有提供一個功能就是隱藏ActionBar,也是一樣只要一段文字就可以達成,actionBar.hide指的是將ActionBar隱藏起來,下面的範例一樣是針對help的Activity進行修改。 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_help); ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setIcon(R.drawable.help); actionBar.hide(); }
可以看到ActionBar完全消失了,如果要顯示ActionBar只要使用actionBar.show就可以了

[Android] Activity切換

[Android] Activity切換

假設手機頁面切換只需要置換背景圖示、文字內容、文字顏色及排版等等,只需要用到setContent就可以置換layout(請參考此篇http://style77125tech.pixnet.net/blog/post/13432877),但如果是要Activity的置換就不能僅靠改變layout就好,需要移交主控權到另外一個Activity,移交主控權的方法,可在主程式裡使用startActivity()這方法來呼叫另外一個Activity,但是關鍵並不是在這一個startActivity這個方法,而是在Intent(就如同英文字意一樣,想要、企圖之意)這個物件,告訴主程式自己是什麼,想要到什麼地方去,這就是intent物件所處理的事。
小試身手小範例:
Java檔 (兩個Activity兩個class)
第一個class TestExam001.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class TestExam001 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main001);
Button button = (Button)findViewById(R.id.button01);
button.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setClass(TestExam001.this, TestExam002.class);
startActivity(intent); 
TestExam001.this.finish();
}
});
}
}
第二個class TestExam002.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class TestExam002 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main002);
Button button = (Button)findViewById(R.id.button02);
button.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setClass(TestExam002.this, TestExam001.class);
startActivity(intent); 
TestExam002.this.finish();
}
});
}
}
XML檔 (兩個Activity兩個對應的layout)
第一個layout  main001.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Activity 001"
android:textSize="50sp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button01"
android:text="Go to Activity 002"
android:textSize="17sp"
/>
</LinearLayout>
AndroidManifest.xml檔
Hint:請記得在AndroidManifest.xml添增一個新的activity並給予名字,否則會出錯喔!然而在一個程式內架設有多個Activity,系統要如何決定以哪一個為entry point呢?在AndroidManifest.xml內有一行為<category android:name="android.intent.category.LAUNCHER" /> 這就表示程式會先執行這一個Activity
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.sam.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TestExam001"
                  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=".TestExam002"></activity>
    </application>
</manifest>
Ps.這兩個java程式在最後都使用finish()這方法,代表這個activity已經運行完畢,當系統接收到這一個指令的時候會關閉此activity,如果這時手機按下back按鍵,並不會回復到上一個Activity的畫面,如果需要讓使用者在按下back鑑可以回到之前的畫面,就必須將這一個finish()刪掉。
device043  device044    

Android Notification的setLatestEventInfo()怎麼代替

Android Notification的setLatestEventInfo()怎麼代替 



在做Android 4.4.2下的APP開發時,使用了Notification的setLatestEventInfo()方法時,Eclipse出現了嘆號警告提示,setLatestEventInfo()該方法已被deprecate,不建議使用了。
  1. /**
  2.      * @hide
  3.      */
  4.     public Notification(Context context, int icon, CharSequence tickerText, long when,
  5.             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
  6.     {
  7.         this.when = when;
  8.         this.icon = icon;
  9.         this.tickerText = tickerText;
  10.         setLatestEventInfo(context, contentTitle, contentText,
  11.                 PendingIntent.getActivity(context, 0, contentIntent, 0));
  12.     }
複製代碼


    這個構造函數被hide,setLatestEventInfo方法也被deprecate,不建議使用,提示使用Notification.Builder。
    在4.0.3平台也就是API Level 15中,使用Notification的setLatestEventInfo()函數時,也會顯示成setLatestEventInfo() 效果,查看文檔發現,在API Level 11中,該函數已經被替代,不推薦使用了。

    在不同的版本下Notification使用有一些不同,涉及到改成Builder的使用,現在網上大多數資料還是API Level 11版本前的用法介紹,如果不熟悉的話,會繞一些彎路。

    現在總結如下,希望對看到這篇文章的有所幫助。

    低於API Level 11版本(即Android 2.3.3之前的系統)中,setLatestEventInfo()函數是唯一的實現方法。前面的有關屬性設置這裡就不再提了,網上資料很多。

  1. Intent  intent = new Intent(this,MainActivity);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);  
  3. notification.setLatestEventInfo(context, title, message, pendingIntent);          
  4. manager.notify(id, notification);  
複製代碼

    高於API Level 11,低於API Level 16 (Android 4.1.2)版本的系統中,可使用Notification.Builder來構造函數。但要使用getNotification()來使notification實現。此時,前面版本在notification中設置的Flags,icon等屬性都已經無效,要在builder裡面設置。
  1. Notification.Builder builder = new Notification.Builder(context)  
  2.             .setAutoCancel(true)  
  3.             .setContentTitle("title")  
  4.             .setContentText("describe")  
  5.             .setContentIntent(pendingIntent)  
  6.             .setSmallIcon(R.drawable.ic_launcher)  
  7.             .setWhen(System.currentTimeMillis())  
  8.             .setOngoing(true);  
  9. notification=builder.getNotification();  
複製代碼

    高於API Level 16的版本,就可以用Builder和build()函數使用notification了。
  1. Notification notification = new Notification.Builder(context)    
  2.          .setAutoCancel(true)    
  3.          .setContentTitle("title")    
  4.          .setContentText("describe")    
  5.          .setContentIntent(pendingIntent)    
  6.          .setSmallIcon(R.drawable.ic_launcher)    
  7.          .setWhen(System.currentTimeMillis())    
  8.          .build();   
複製代碼



注意:

    在構造notification的時候有很多種寫法,但是要注意,用Notification notification = new Notification(); 這種構建方法的時候,一定要加上notification.icon這個設置,不然,程序雖不會報錯,但是會沒有效果。