Android官方文檔筆記
Getting Start
1. Supporting Different Devices
兼容不同的設備
- 適配不同區域語言.
———- 添加不同區域語言的字符串值到相應的文件.
英語(默認區域語言),/values/strings.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">My Application</string>
<string name="hello_world">Hello World!</string>
</resources>
中文,/values-zh/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">我的應用程序</string>
<string name="hello_world">大家好!</string>
</resources>
2.動態引用字符資源.
—–getResources
方法
String hello = getResources().getString(R.string.hello_world);
—–setText
方法
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);
3.適配不同的屏幕
—–在res/layout
目錄添加目錄和同名的xml文件
MyProject/
res/
layout/ /*默認適配
main.xml
layout-large/ /*大屏幕適配
main.xml
layout-land/ /*橫屏適配
main.xml
4.創建不同的Bitmap以適應不同的精度
- xhdpi: 2.0
- hdpi: 1.5
- mdpi: 1.0 (基準)
- ldpi: 0.75
——–將圖片文件放入相應的drawable資源目錄中:
Note:任何時候,當引用@drawable/awesomeimage時系統會根據屏幕的分辨率選擇恰當的bitmap。
MyProject/
res/
drawable-xhdpi/
image.png
drawable-hdpi/
image.png
drawable-mdpi/
image.png
drawable-ldpi/
image.png
Note:低密度(ldpi)資源是非必要的,當提供了hdpi的圖像,系統會把hdpi的圖像按比例縮小一半,去適配ldpi的屏幕。
2. Activity的生命週期
onPause
方法可做以下事情
停止動畫或者是其他正在運行的操作,那些都會導致CPU的浪費.
提交在用戶離開時期待保存的內容(例如郵件草稿).
釋放系統資源,例如broadcast receivers, sensors (比如GPS), 或者是其他任何會影響到電量的資源。
Note:如果activity實際上是要被Stop,那麼我們應該爲了切換的順暢而減少在OnPause()方法裏面的工作量。
onResume
- 應該實現onResume()來初始化那些在onPause方法裏面釋放掉的組件,並執行那些activity每次進入Resumed state都需要的初始化動作 (例如開始動畫與初始化那些只有在獲取用戶焦點時才需要的組件)
onStop
- 我們應該使用onStop()來執行那些CPU intensive的shut-down操作,例如往數據庫寫信息。我們需要使用onStop()來釋放資源,從而避免內存泄漏。
恢復數據
☆☆☆ 通過重寫onSaveInstanceState
方法來保存Activity被意外終止的信息
public void onSaveInstanceState(Bundle savedInstanceState) {
// 保存用戶之前使用的一些數據
savedInstanceState.putInt(STATE_SCORE, mCurrent);
//保存用戶之前的視圖信息
super.onSaveInstanceState(savedInstanceState);
}
☆☆☆ 通過重寫onCreate
方法來恢復Activity被意外終止的信息
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 優先申明這個子類
if (savedInstanceState != null) {
mCurrent = savedInstanceState.getInt(STATE_SCORE);
} else {
}
}
☆☆☆ 我們也可以選擇實現 onRestoreInstanceState()方法恢復數據。
public void onRestoreInstanceState(Bundle savedInstanceState) {
// 通常通過調用此類來恢復視圖信息
super.onRestoreInstanceState(savedInstanceState);
mCurrent = savedInstanceState.getInt(STATE_SCORE);
}
-onRestoreInstanceState()方法會在 onStart() 方法之後執行. 系統僅僅會在存在需要恢復的狀態信息時纔會調用 onRestoreInstanceState() ,不需要檢查 Bundle 是否爲null。
3. Buiding a Dynamic UI with Fragments
使用Fragment構建一個可交互UI界面
——項目源碼:FragmentBasic
創建fragment模塊類
public class ArticleFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 爲碎片填充視圖 return inflater.inflate(R.layout.article_view, container, false); } }
靜態添加fragment碎片(XML)
<fragment android:name="com.example.android.fragments.HeadlinesFragment" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" />
或動態添加fragment碎片
———- 創建一個佈局容器:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
———- 往容器中添加視圖
//當容器內容不爲空時,不執行後面的語句。
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
HeadlinesFragment firstFragment = new HeadlinesFragment();
//用來獲取fragment的Intent額外信息
firstFragment.setArguments(getIntent().getExtras());
//開啓事務添加碎片並提交
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
4.HeadLineFragment
類繼承ListFragment後直接setListAdapter即可顯示列表
setListAdapter(new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1,String));
5.☆覆寫列表的點擊事件,提供接口讓父Activity實現
ArticleSelected articalFragment
......
public void onListItemClick(ListView l, View v, int position, long id){
articalFragment.articleSelected(position);
}
public interface ArticleSelected{
public void articleSelected(int poisition);
}
6.☆父Activity實現接口並setArgument.MainActivity
public void articleSelected(int poisition) {
ArticalFragment articalFragment = new ArticalFragment();
Bundle bundle = new Bundle();
bundle.putInt(ArticalFragment.KEY, poisition);
articalFragment.setArguments(bundle);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, articalFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
7.☆在onAttach
中回調接口
public void onAttach(Context context) {
super.onAttach(context);
try {
articalFragment = (ArticleSelected) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHeadlineSelectedListener");
}
8.Articlefragment
類在onStart
中獲取傳來的信息
public void onStart(){
super.onStart();
Bundle bundle = getArguments();
if(bundle != null){
setTextView(bundle.getInt(KEY));
}
public void updateArticleView(int position) {
TextView article = (TextView) getActivity().findViewById(R.id.article);
article.setText(Ipsum.Articles[position]);
}
}
4.Save Data
數據保存
1.SharedPreference保存
———- 獲取SharedPreference
getSharedPreferences()
— 需要多個名稱參數來區分shared preference文件, 名稱可以通過第一個參數來指定。可在app中通過任何一個Context 執行該方法Context context = getActivity(); SharedPreferences sharedPref = context.getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE);
- getPreferences() — 當activity僅需要一個shared preference文件時。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
———- 寫Shared Preference
通過執行edit()創建一個 SharedPreferences.Editor。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPref.edit (); editor.putInt(getString (R.string.saved_high_score), newHighScore); editor.commit();
———- 讀Shared Preference
提供一個默認的value作爲查找的key不存在時函數的返回值。
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); int defaultValue = getResources().getInteger (R.string.saved_high_score_default); long highScore = sharedPref.getInt(getString(R.string.saved_high_score), default);
2.保存文件
- Internal storage(內部儲存):
1.總是可用的
2.這裏的文件默認只能被我們的app所訪問。
3.當用戶卸載app的時候,系統會把internal內該app相關的文件都清除乾淨。
4.Internal是我們在想確保不被用戶與其他app所訪問的最佳存儲區域。
- External storage(外部儲存):
1.並不總是可用的,因爲用戶有時會通過USB存儲模式掛載外部存儲器,當取下掛載的這部分後,就無法對其進行訪問了。
2.是大家都可以訪問的,因此保存在這裏的文件可能被其他程序訪問。
3.當用戶卸載我們的app時,系統僅僅會刪除external根目錄(getExternalFilesDir())下的相關文件。
4.External是在不需要嚴格的訪問權限並且希望這些文件能夠被其他app所共享或者是允許用戶通過電腦訪問時的最佳存儲區域。
保存內部儲存
① 使用File()
構造器在目錄下創建一個新的文件
File file = new File(context.getFilesDir(), filename);
② openFileOutput()
獲取一個FileOutputStream
用於寫文件到internal目錄(可設置不可讀寫)
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
③使用createTempFile()
緩存文件
———- 緩存目錄下的文件一旦不再需要馬上被刪除
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
catch (IOException e) {
// Error while creating file
}
return file;
}
保存外部儲存
申明權限(只讀)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Note:對於內存卡,不需要聲明任何權限,默認有讀寫程序目錄下文件的權限
- 保存文件到外部卡
———- 判斷外部卡是否可用。若返回狀態爲MEDIA_MOUNTED
, 則可以讀寫
/* 檢查外部儲存卡是否可讀可寫 */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState ();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/* 檢查外部儲存卡是否至少可讀*/
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState ();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
儘管外部儲存卡對於用戶與其他app是可修改的,我們可能會保存下面兩種類型的文件。
Public files :用戶卸載我們的app時,這些文件應該保留。例如,被我們的app拍攝的圖片或者下載的文件。
public File getAlbumStorageDir(String albumName) { // 需要帶有一個特定的參數來指定這些public的文件類型. File file = new File (Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }
Private files: 在app被卸載時刪除。
如果剛開始的時候,沒有預定義的子目錄存放我們的文件,可以在
getExternalFilesDir()
方法中傳遞null. 它會返回app在external storage下的private的根目錄。public File getAlbumStorageDir(Context context, String albumName) { File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }
刪除文件
myFile.delete();
如果文件是保存在internal storage,我們可以通過Context來訪問並通過執行deleteFile()進行刪除
myContext.deleteFile(fileName);
3.保存到SQLite數據庫
建立數據庫結構
創建數據庫
導入數據
數據庫操作
增
刪
- 改
- 查
5.Interacting with oher apps.
與其它App交互
隱式Intent(查看網頁)
Uri webpage = Uri.parse("http://www.android.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage ); //創建選擇程序界面 Intent Chooser = Intent.createChooser(webIntent,"選擇界面標題"); // 判斷是否有程序接收此Intent PackageManager packageManager = getPackageManager(); List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0); boolean isIntentSafe = activities.size() > 0; if(isIntentSafe){ startActivity(chooser); }
接收Activity返回的結果(讀取聯繫人信息)
發送
static final int PICK_CONTACT_REQUEST = 1;
...
private void pickContact() {
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}
接收
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
Uri contactUri = data.getData();
String[] projection = {Phone.NUMBER};
Cursor cursor = getContentResolver()
.query(contactUri, projection, null, null, null);
cursor.moveToFirst();
int column = cursor.getColumnIndex(Phone.NUMBER);
String number = cursor.getString(column);
}
}
}
- Intent過濾
靜態添加Intent-Filter
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*"/>
</intent-filter>
</activity>
處理Intent
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
Uri data = intent.getData();
//處理圖片信息
if (intent.getType().indexOf("image/") != -1) {
//處理文字信息
} else if (intent.getType().equals("text/plain")) {
}
}
返回Result
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();
簡單的只需要返回int值
setResult(RESULT_COLOR_RED);
finish();