1. 程式人生 > >Android 四大元件,五大儲存,六大布局

Android 四大元件,五大儲存,六大布局

Android 四大元件

android四大元件分別是:Activity, service,content provider,broadcast receiver

一、Activity

1、概念:

android 中,Activity 相當於一個頁面,可以在Activity中新增Button、CheckBox 等控制元件,一個android 程式有多個Activity組成。

2、生命週期:

這裡寫圖片描述

3、四中啟動模式

Standard 模式 : standard 模式是android 的預設啟動模式,在這種模式下,activity可以有多個例項,每次啟動Activity,無論任務棧中是否已經存在這個activity的例項,系統都會建立一個新的activity例項。

SingleTop 模式: 棧頂模式,當一個singleTop模式的activity 已經位於棧頂時,再去啟動它時,不在建立例項,如果不在棧頂,就會建立例項。

SingleTask 模式 : 單任務模式,如果啟動的activity 已經存在於 任務棧中,則會將activity移動到棧頂,並將上面的activity出棧,否則建立新的例項

SingleInstance 模式 :單例項模式,一個activity 一個棧。

4、三種跳轉方式

顯示啟動
Intrent 內部直接宣告要啟動的activity所對應的的class

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intnet);

隱式啟動
進行三個匹配,一個是activity,一個是category,一個是data,全部或者部分匹配,應用於廣播原理

  • 清單檔案中 裡配置activity屬性,activity的名字要和跳轉內容一樣
<activity 
	android:name="com.exanple.android.tst.secondActivity"
	android:label = @string/title>
	<intent=filter>
		<action android:name="com.exanple.android.tst.secondActivity/>
		<category android:name="android.intent.category.DEFAULT"/>
	<intent-filter/>
</activity>
  • 在需要跳轉的地方
Intent intent = new Intent("com.example.android.tst.secondActivity");
startActivity(intnet);

跳轉後再返回,能獲取返回值

Intent in = new Intent(MainActivity.this,OtehrActivity.class);
in.putExtra("a",a);
startActivityForResult(in,1000);

在OTherActivity中設定返回值

Intent int = new Intent();
int.putExtra("c",c);
setResult(1001,int);
finish();

在MainActivity中獲取返回值

@Override
protected void onActivityResult(int requestCode, int resultCode	,Intent data) {
	super.onActivityResult(requestCode,resultCode,data);
	if(requestCode == 1000){
		if(resultCode == 1001){
			int c = data.getExtra("c",0);
		}
	}
}

Service

定義一個Server

專案內Server包 右鍵 --> New --> Service --> Service 或者直接建立Class類,繼承Service並重寫IBinder方法

public class MyService extends Service{
	
	public MyService(){
		
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}
}

重寫Service的 onCreate()、onStartCommand()和onDestory()方法。其中 onCreate() 方法在服務建立的時候呼叫、onStartCommand() 方法會在每次服務啟動的時候呼叫、onDestory() 方法會在服務銷燬的時候呼叫。
通常情況下,如果我們希望服務一旦啟動就立刻去執行任務,就可以將邏輯解除安裝onStartCommand() 方法裡。
另外需要注意的是,每個服務都需要在Androidmanifest.xml 中進行註冊才能生效:

<application
	....>
	...
	<service
		android:name=".MyService"
		android:enabled="true"
		android:exported="true">
	</service>
</application>
啟動和停止服務

啟動服務:

Intent startIntent = new Intent(this, MyService.class);
startService(startIntent); //啟動服務

停止服務:

Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent); //停止服務
使用前臺服務

前臺服務與普通服務的最大區別在於,它會一直有一個正在執行的圖示在系統的狀態列中,下拉狀態列後可以看到更加詳細的內容,非常類似於通知的效果。

public class MyService extends Service{
	Intent intent = new Intent(this, MainActivity.class);
	PendingIntent pi = PendingIntent.getActivity(this, 0 , intent, 0);
	Notification notification  = new NotificationCompat.Builder(this)
		.setContentTitle(" this is content titile")
		.setContentText("this is content text")
		.setWhen(System.currentTimeMillis())
		.setSmallIcon(R.mipmap.ic_launcher);
		.setLargeIcon(BitmapFactory.decodeResource(getResource(),
			R.mipmap.ic_launcher))
		.setContentIntent(pi)
		.build();
	startForeground(1,notification);
}

構造一個Notification物件後並沒有使用NotificationManager 來講通知顯示出來,而是呼叫了startForeground()方法,該方法會將MyService變成一個前臺服務,並在系統狀態列中顯示出來。

使用IntentService

服務中的程式碼都預設執行在主執行緒中,如果直接在服務中執行耗時操作很容易出現ANR(Application not Responding)
所以這個時候需要用到Android多執行緒程式設計技術,我們應該在服務的每個具體的方法裡啟動一個子執行緒,然後在這裡去處理那些耗時的操作:

public class MyService extends Service{
	...
	@Override
	public int onStartCommand(Intent intent , int flags, int startId){
		new Thread(new Runnable(){
			public void run(){
				//處理具體的邏輯
			}
		}).start();
		return super.onStartCommand(intent, flags, startId);
	}
}

但是,這種服務一旦啟動之後,就會一直處於執行狀態,必須呼叫stopService()或者stopSelf()方法才能讓服務停止下來,所以,如果想要實現讓一個服務在執行完畢後自動停止的功能,就可以這樣寫:

public class MySerivce extends Servcie{
	...
	@Override
	public int onStartCommand(Intent intent, int flats , int startId){
		new Thread(new Runnable(){
			public void run(){
				//處理具體的邏輯
				stopSelf();
			}
		});
	}
}

雖說這樣的寫法並不複雜,但是總會有一些程式設計師忘記開啟執行緒或者忘記呼叫stopSelf() 方法。為了簡單建立一個非同步、會自動停止的服務。Android專門提供了一個IntentService類

public class MyIntentService extends IntentService{
	public MyIntentService(){
		super("MyIntentService");  //呼叫父類的有參構造方法
	}
	@Override
	protected void onHandleIntent(Intent intent){	
		//列印當前的執行緒ID
		Log.e("mylog","Thread id is” + Thread.cuttentThread().getId();
	}
	@Override
	public void onDestory(){
		super.onDestory();
		Log.e("mylog","on Destory executed");
	}
}

首先這裡提供一個無參的構造方法,並且必須在其內部呼叫父類的有參構造方法。然後要在子類中去實現onHandleIntent() 這個抽象方法,在這個方法中可以去處理一些邏輯,而且不用擔心ANR,因為這個方法已經是在子執行緒中運行了。
IntentService執行緒的呼叫:

Intent intent = new Intent(this, MyIntentService.class);
startServcie(intent);

如此,執行緒就會自動啟動並執行邏輯,執行完畢後自動關閉。這就是IntentService 的好處,能夠自動開啟和關閉;

Content Provider

對於每一個應用程式來說,如果想要訪問內容提供器中共享的資料,就一定要藉助ContentResolver 類,可以通過Context中的getContentResolver() 方法獲取該類的例項。ContentResolver中提供了一系列的方法用於對資料進行CRUD操作,其中insert() 方法用於新增資料,update() 方法用於更新資料,delete() 方法用於刪除資料,query() 方法用於查詢資料。
不同於SQLiteDatabase,ContentResolver 中的增刪改查都是接收一個URl引數,這個引數被稱為內容URL。內容URL給內容提供器中的資料建立了唯一識別符號,它主要由兩部分組成:authoritypathauthority 是用於對不同的應用程式做區分的,一般為了避免衝突,都會採用程式包名的方式進行命名。path則是用於對同一應用程式中不同的表做區分,通常都會新增到authority後面:

content://com.example.app.provider/table1
content://com.example.app.provider/table2

在使用內容URL作為引數的時候,需要將URL轉換成URL物件:

Uri uri = Uri.parse("content://com.example.app.provider/table1")

現在我們就可以使用這個uri物件來查詢talbe1表中的資料了:

Cursor cursor = getContentResolver().query(
	uri,
	projection,
	selection,
	selectionArgs,
	sortOrder
);

對應引數的解釋:

query()方法引數 對應SQL部分 描述
uri from table_name 指定查詢某個應用程式下的某個表
projection select column1, column2 指定查詢的列名
selection where column=value 指定where約束條件
selectArgs - 為where中的佔位符提供具體的值
orderBy order by column1, column2 指定查詢結果的排序方式

查詢完之後,就可以從遊標中取值了:

if(cursor != null){
	while(cursor.moveToNext()) {
		String column1 = cursor.getString(cursor.getColumnIndex("column1"));
		int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
	}
	cursor.close();
}
增刪改查

新增資料

ContentValues values = new ContentValues();
values.put(“column1”, "text");
values.put("column2", 1);
getContentResolver().insert(uri, values);

更新資料

ContentValues valuse = new ContentValues();
valuse.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[]{"text", 1});

刪除資料

getContentResolver().delete(uri , "column2 = ?", new String[]{ "1"});
例項.

讀取系統聯絡人
讀取系統聯絡人需要宣告許可權,如果系統是6.0以後的,需要申請執行時許可權

if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) 
	!= PackageManager.PERMISSION_GRANTED) {
		ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
	}else {
		readContacts();  //讀取聯絡人
	}
private void readContacts(){
	Cursor cursor = null;
	try{
		//查詢聯絡人資料
		cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
		if(cursor!=null){
			while(cursor.moveToNext()){
				//獲取聯絡人姓名
				String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
				//獲取聯絡人電話號碼
				String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
				list.add(name+"\n"+number);
			}
		}
	}catch(Exception e){
		e.printStackTrace()
	}finally{
		if(cursor != null){
			cursor.close();
		}
	}
}

@Override
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults){
	switch(requestCode){
		case 1:
			if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
				readContacts();
			}else {
				//您拒絕了許可權
			}
	}
}
建立自己的內容提供器

建立自己的內容提供器,需要去繼承 ContentProvider 類,ContentProvider 類中有6個抽象方法,我們在使用子類繼承它的時候,需要將這6個方法全部重寫。

public class MyProvider extends ContentProvider{
	@Override
	public boolean onCreate() {
		return false;
	}
	@Override
	public Cursor query(Uri uri, String[] projection, Stirng selection, String[] selectionArgs, String sortOrder){
		return null;
	}
	@Overrride
	public Uri insert(Uri uri , ContentValues values){
		return null;
	}
	@Override
	public int update(Uri uri, ContentValuse values, String selection, String[] selectionArgs){
		return 0;
	}
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs){
		return 0;
	}
	@Override
	public String getType(Uri uri){
		return null;
	}
}

URI 的主要格式有以下兩種

content://com.example.app.provider/table1
content://com.example.app.provider/table1/1

* : 表示匹配任意長度的任意字元
# : 表示匹配任意長度的數字

//一個能夠匹配任意表的內容URI格式就可以寫成:
content://com.example.app.provider/*
//一個能夠匹配表中任意一行資料的內容URI格式就可以寫成:
content://com.example.app.provider/table1/#

Broadcast Receiver

android 廣播分為兩個角色:廣播發送者、廣播接收者
android 廣播:
1),用於不同元件間的通訊(含:應用內/不同應用之間)
2),用於多執行緒通訊
3),與android系統的通訊

自定義廣播接收者
  • 繼承BroadcastReceive 基類
  • 必須重寫抽象方法onReceive()方法
1,廣播接收器收到相應廣播後,會自動呼叫onReceive() 方法
2,一般情況下,onReceive方法會會涉及與其他元件之間的互動,如 傳送Notiotification,啟動server等
3,預設情況下,廣播接收器執行在UI執行緒,因此,onReceive方法不能執行耗時操作,否則將導致ANR
廣播接收器註冊

註冊的方式有兩種:靜態註冊、動態註冊
靜態註冊

  • 註冊方式:在AndroidManifest.xml 裡通過<receive 標籤宣告
  • 屬性說明
<receiver
	android:enable="true"/"false"
	//此broadcastReceiver 是否接受其他應用發出的廣播
	//預設值時由receiver 中d有無inter-filter決定,如果有,預設true,否則預設false
	android:exported="true"/"false"
	android:icon="drawable resource"
	android:label="string resource"
	//繼承BroadcastReceiver子類的類名
    android:name=".mBroadcastReceiver"
//具有相應許可權的廣播發送者傳送的廣播才能被此BroadcastReceiver所接收;
    android:permission="string"
//BroadcastReceiver執行所處的程序
//預設為app的程序,可以指定獨立的程序
//注:Android四大基本元件都可以通過此屬性指定自己的獨立程序
    android:process="string" >

//用於指定此廣播接收器將接收的廣播型別
//本示例中給出的是用於接收網路狀態改變時發出的廣播
 <intent-filter>
	<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
 </intent-filter>
 </receiver>

註冊示例:

<receiver 
    //此廣播接收者類是mBroadcastReceiver
    android:name=".mBroadcastReceiver" >
    //用於接收網路狀態改變時發出的廣播
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

當此APP首次啟動時,系統會自動例項化mBroadcastReceiver類,並註冊到系統中。

動態註冊

  • 註冊方式:在程式碼中呼叫Context.registerReceiver() 方法
  • 具體程式碼如下:
	// 1. 例項化BroadcastReceiver子類 &  IntentFilter
     mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
     IntentFilter intentFilter = new IntentFilter();

    // 2. 設定接收廣播的型別
    intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

    // 3. 動態註冊:呼叫Context的registerReceiver()方法
     registerReceiver(mBroadcastReceiver, intentFilter);


//動態註冊廣播後,需要在相應位置記得銷燬廣播
unregisterReceiver(mBroadcastReceiver);

特別注意
動態廣播最好在onResume中註冊, onPause登出
原因:
1,對於動態廣播,有註冊必然得有登出,否則會導致記憶體洩漏
2,onPause在App死亡前一定會被執行,從而保證app死亡前一定會被登出,從而防止記憶體洩漏

兩種註冊方式的區別

在這裡插入圖片描述

廣播的傳送

廣播的傳送 = 廣播發送者 將此廣播的意圖(intent)通過 sendBroasdcast() 方法傳送出去
廣播的型別

  • 普通廣播 系統廣播 有序廣播 粘性廣播 App 應用內廣播
特別注意:

對於不同註冊方式的廣播接收器回撥OnReceive(Context context,Intent intent)中的context返回值是不一樣的:

  • 對於靜態註冊(全域性+應用內廣播),回撥onReceive(context,
    intent)中的context返回值是:ReceiverRestrictedContext;
  • 對於全域性廣播的動態註冊,回撥onReceive(context, intent)中的context返回值是:Activity
    Context;
  • 對於應用內廣播的動態註冊(LocalBroadcastManager方式),回撥onReceive(context,
    intent)中的context返回值是:Application Context。
  • 對於應用內廣播的動態註冊(非LocalBroadcastManager方式),回撥onReceive(context,
    intent)中的context返回值是:Activity Context;

Android 五大儲存

SharedPreferences 方式

SharedPreferences 是使用鍵值對的方式進行儲存資料的。
想要使用SharedPreferences 來儲存資料,首先主要獲取到SharedPreferences 物件。Android提供了三種方法用於獲取SharedPreferences物件:
1,Context類中的getSharedPreferences()方法

//此方法接收兩個引數,一個引數用於指定SharedPreferences檔案的名稱,如果指定的檔案不存在則會建立一個,SharedPreferences檔案都是存放在/data/data/<package name>/shared_prefs/目錄下
//第二個引數用於指定操作模式,目前只有MODE_PRIVATE這種模式,和直接傳入0效果相同
SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age",13);
editor.putBoolean("married",false);
editor.apply();

2,Activity類中的getPreferences()方法

//這個方法和Context中的getSharedPreferences()方法很類似,不過它只接收一個操作模式,因為使用這個方法時會自動將當前活動的類名作為SharedPreferences的檔名

3,PreferencesManager類中的getDefaultSharedPreferences()方法

//這是一個靜態方法,它接收一個Context引數,並自動使用當前應用程式的包名作為字首來命名SharedPreferences檔案

得到了SharedPreferences物件後, 就可以開始想SharedPreferences檔案中儲存資料了,主要可以分為三步:
(1)呼叫SharedPreferences物件的edit()方法來獲取一個SharedPreferences.Editor物件
(2)向SharedPreferences.Editor 物件中新增資料,比如新增一個布林值,可以使用putBoolean() 方法
(3)呼叫apply()方法的新增的資料提交,從而完成資料儲存操作

SharedPreferences中讀取資料
SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE	);
String name = pref.getString("name","");
int age = pref.getInt("age",0);
boolean married = pref.getBoolean("married", false);

檔案儲存方式

SQList 儲存方式

Android 為了讓我們能夠更加方便的管理資料庫,專門提供了一個SQLiteOpenHelper 幫助類,藉助這個類可以非常簡單的將資料庫進行建立好升級。
SQLiteOpenHelper 中有兩個非常重要的例項方法,getReadableDatabase()getWritableDatabase() 。這兩個方法可以建立或者開啟一個現有的資料庫(如果資料庫存在則直接開啟,否則建立一個新的資料庫),並返回一個可對資料庫進行讀寫操作的物件。不同的是,當資料庫不可寫入(如磁碟空間已滿),getReadableDatabase方法返回的物件將以只讀的方式開啟資料庫,而getWeitableDatabase則出現異常

例子(在指定路徑下建立資料庫檔案 .db )

public class MainActivity extends Activity {
	public static final String PATH_ONE = "KogBill";
	public static final String PATH_NAME = "KogBill.db";
	private SQLiteDatabase db;    //宣告SQLiteDatabase ,該物件可以操作資料庫

	String path = Environment.getExternalStorageDirectory().getAbsolutePath();
	String path1 = path + File.separator + PATH_ONE;   //需要建立的路徑
	String path2 = path + File.separator + PATH_ONE + 
			File.separator + PATH_NAME;  							//需要建立的檔案

	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		File f = new File(path1);
		if( !f.exists()){  //建立資料庫檔案路徑
			f.mkdirs();
		}	
		//例項化MySQLiteHelper ,建立指定目錄下資料庫檔案,並建立表
		MySQLiteHelper mSQL = new MySQLiteHelper(MainActivity.this, path2);
		db = mSQL.getWritableDatabase();
	}

	class MySQLiteHelper extends SQLiteOpenHelper{
			private static final int DATABASE_VERSION = 1;//資料庫版本號
			private static final String CREATE_TABLE = "create table kog_bill ("
		            + "_id integer primary key autoincrement,"
		            + "date text, "
		            + "breakfast text, "
		            + "lunch text,"
		            + "dinner text,"
		            + "happy text,"
		            + "other text,"
		            + "spare text)";
			
			//方便建立例項,簡化構造方法,方法內呼叫4引數構造方法
			//引數 name 可以是 資料庫名稱,也可以資料庫檔案路徑(即可以指定資料庫檔案路徑)
			public MySQLiteHelper(Context context, String name) {
				this(context, name, null, DATABASE_VERSION);
			}
			//必須要實現的方法
			public MySQLiteHelper(Context context, String name, CursorFactory factory, int version) {
				super(context, name, factory, version);
			}
	
			@Override
			public void onCreate(SQLiteDatabase db) {
				// 第一次建立資料庫時 才會呼叫
				Log.e("mylog", "建立資料庫表");
				db.execSQL(CREATE_TABLE);
			}
	
			@Override
			public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			}
			
		}
}

根據上述程式碼,便獲得db物件,通過db(SQLiteDatabase)可進行資料庫的操作,如 db.query() db.delete()

如果我們想在建立一個數據庫表,參照上述程式碼,可以在SQLiteOpenHelper的onCreate方法中加入語句:

@Override
public void onCreate(SQLiteDatebase db) {
	db.execSQL(CREATE_TABLE);
	db.execSQL(CREATE_BOOK);  //新建立一個數據庫表
}

然後重新執行一下,發現並沒有建立成功,因為KogBill.db資料庫已經存在,所以MySQLiteHelper 中的onCreate方法都不會執行,解決這個辦法的方法很簡單,只需要將db檔案刪除,重新執行,便可成功,但是原來資料庫中的資料都會被刪除。所以需要用到MySQLiteHelper中的update方法。

class MySQLiteHelper extends SQLiteOpenHelper{
	.....
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
		db.execSQL("drop table if exists book");  //如果已經存在就刪除,防止重複建立
		onCreate(db);  // 再次執行onCreate 方法
	}
}

但是onUpgrade方法預設是不執行的,如何讓onUpgrade方法執行,需要用到MySQLiteHelper 構造引數中的版本號:

private static final int DATABASE_VERSION = 1;//  將版本號 由 1 改為2 

這裡將資料庫版本號由1改為2,表示對資料庫的升級

資料庫的增刪改查

新增資料

ContentValues values = new ContentValues();
	values.put("date", str1.isEmpty()?"0.0":str1);
	values.put("breakfast", ""+str2);
	values.put("lunch", ""+str3);
	values.put("dinner", ""+str4);
	values.put("happy", ""+str5);
	values.put("other", ""+str6);
	values.put("spare", ""+str7);
	long ii = db.insert("kog_bill", "", values);
	values.clear();
	if(ii != -1) {
		Utils.showToast("儲存成功!", MainActivity.this);
	}else {
		Utils.showToast("儲存失敗!", MainActivity.this);
	}

更新資料

ContentValues valus = new ContentValues();
valuse.put("other","12");
db.update("kogBill", values, "_id=?",new String[]{id});

刪除資料

db.delete("kogBill", "_id=?",new String[]{id});

查詢資料

db.query("kog_bill", new String[]{"_id","date","breakfast","lunch","dinner","happy","other","spare"}
		, null, null, null, null, "date desc");
使用SQL操作資料庫

雖然Android 已經給我們提供了非常方便的API用於操作資料庫,不過總會有些人不習慣去使用這些輔助行的方法,而是更加青睞於直接使用SQL來操作資料庫,當然Android也是提供的。
新增資料

db.execSQL("insert into kogBill ("date","breakfest","lunch","dinner","happy","other","spare") values (?,?,?,?,?,?,?)", new String[]{"1921-1-1",“123”,“1”,“1”,“11”,“2”,“3”});

更新資料

db.execSQL("update kogBill set other = ? where _id = ? ", new String[]{"12",id});

刪除資料

db.execSQL("delete from kogBill where _id = ?”, new String[]{id});
使用 LitePal 操作資料庫

假設編譯環境為AndroidStudio。
1,引進包

dependencies{
	compile fileTree(dir:'libs', include:['*.jar'])
	compile 'com.android.support:appcompat-v7:23.2.0'
	testCompile 'junt:junt:4.12'
	compile 'org.litepal.android:core:1.3.2'   //引入litepal包
}

2,配置litepal.xml 檔案
右鍵app/src/main 目錄->New -> Directory ,建立一個assets目錄,然後在 assets目錄下再新建一個litepal.xml 檔案,接著編輯檔案中的內容

<?xml version='1.0' encoding="utf-8"?>
<litepal>
	<dbname value = "BookStore"></dbname>
	<version value="1"></version>
	<list></list>
</listepal>

其中,<dbname 標籤用來指定資料庫名,<version 用來指定資料庫版本號,<list 標籤用來指定所有對映模型。
最後還需要在配置以下 LitePalApplication, 修改AndroidManifest.xml 中的程式碼

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.example.litepaltest" >
	<application
		android:name="org.litepal.LitePalApplication"  //配置 LitePalApplication
		android:allowBackup="true"
		.....
	</application>
</manifest>

以上,LitePal的配置工作已經結束了,接下來使用LitePal。
首先將需要實現 javabean類 對應 資料庫表.
然後將javabean類新增到對映模型列表中,修改litepal.xml 中的程式碼

<litepal>
	<dbname value="kogBill" ></dbname>
	<version value="1"></version>
	<list>
		<mapping class="com.example.litepaltest.book"></mapping>  //javabean類的路徑
	</list>

這樣所有工作就已經完成,現在只要進行任意一次資料庫的操作,資料庫db檔案就會自動建立,比如:

Connector.getDatabase();
操作資料

如果需要對某個表進行資料操作,需要讓其對應的javaBean類繼承DataSupport

public class Book extends DataSupport { //讓對應的類繼承DataSupport
	...
}

接下來,進行新增資料的操作:

Book book = new Book();
book.setName("...");
book.setAuthor("...");
book.setPages(234);
book.setPrice(12,21);
book.setPress("unkow");
book.save();  //執行sava 就可以插入資料了

執行更新資料:

Book book = new Book();
book.setPrice(11.11);
book.setPress("Anchor");
book.updateAll("name = ?  and authro = ?","..","...");

刪除資料:

DataSupport.deleteAll(Book.class, "price<?","13");

查詢資料:

//查詢所有
List<Book> books = DataSupport.findAll(Book.class);  
// 查詢第一條
List<Book> books = DataSupport.findFirst(Book.class);
//查詢最後一條
List<Book> books = DataSupport.findLast(Book.class);
//查詢那幾列的資料
List<Book> books = DataSupport.select("name","author).find(Book.class);
//條件查詢, 頁面大於400
List<Book> books = DataSupport.where("pages >?","400").find(Book.class);
//將 price 降序排序
List<Book> books = DataSupport.order(price desc").find(Book.class);
//查詢前3條
List<Book> books = DataSupport.limit(3).find(Book.class);
//從下表1開始,往後查詢3條
List<Book> boods = DataSupport.limit(3).offset(1),find(Book.class)

當然這些方法也可以組合起來使用:


List<Book> books = DataSupport.select("name","author","pages")
															.where("pages>?”,"400")
															.order("pages")
															.limit(10)
															.offset(10)
															.find(Book.class);

如果有些特殊查詢,使用上述方法無法查詢時,可以使用如下語句:

Cursor c  = DataSupport.findBySQL("select * from Book where pages > ? and price < ?”, 
		"400","20”);

內容提供器(Conent Provider)方式

網路儲存方式

Android 六大布局

LinearLayout 線性佈局

線性佈局,如名字所描述的那樣,這個佈局將它所包含的控制元件線上性方向上一次排列,方向分為 水平方向和數值方向。
屬性 android:orientation = “vertical” | “horizontal” 豎直或水平,預設水平
屬性 android:layout_gravity = “top” | “center” | “bottom” 內部的佈局方式
屬性 android:gravity = “top”|"center”|“bottom” 相對於父容器的對齊方式
屬性 android:layout_weidht 使用比例方式執行控制元件的大小,在手機螢幕適配方面起到非常重要的作用

TableLayout 表格佈局

FrameLayout 幀佈局

RelativeLayout 相對佈局

GridLayout 網格佈局

AbsoluteLayout 絕對佈局