2015年8月22日 星期六

Activityc和Service之間的值傳遞

StartService這種方式是無法將Service運算的數據返回給Activity,也就是說Activity丟指令給Service去做,但Service做到什麼程度,做完了還是正在做...等這些訊息,Activity是無法得知的,所以就需要用bound service來解決這問題的,下面是基本使用方法:

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="com.example.binderservice01.MainActivity" >

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="綁定完成操作" />

</RelativeLayout>

MainActivity.java:

public class MainActivity extends Activity {
private Button btn1 ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button)findViewById(R.id.btn1);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
}
});
}
//接下來用匿名內部類來生成一個ServiceConnection對象。他是一個接口
ServiceConnection conn = new ServiceConnection(){
//當如果調用上面的bindService去綁定service成功的話,就會去調用                                                 onServiceConnected
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
FirstBinder binder = (FirstBinder)service;
String data = binder.getData();
System.out.println("得到Service 的binder的值data--->"+data);
}
//當綁定service斷開時候,就會調用onServiceDisconnected
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
};
}

SecondService.java:

public class SecondService extends Service {

//當其他的應用程序組件(Activity)綁定至當前的Service,就會調用這方法
@Override
public IBinder onBind(Intent intent) {
//因為FirstBinder繼承了Binder,Binder又是IBinder的子類
//,所以我們也可以認為FirstBinder是IBinder的子類,就可以return binder
IBinder binder = new FirstBinder();
return binder;
}

class FirstBinder extends Binder{
public String getData(){
return "test data";
}
}
}

08-23 13:57:28.947: I/System.out(19095): 得到Service 的binder的值data--->test data

總結: 首先在Service裡面先定義一個class Binder的實現類,然後裡面去添加一個方法,然後在
onBind這個方法去返回這個FirstBinder對象,之後在Activity去調用bindService,在調用時要先實現一個ServiceConnection這個接口。當綁定成功時候就會通過ServiceConnection來調用
onServiceConnected來取得Service裡binder對象的數據取出來,透過這個機制就可以讓Activity去調用Service的方法得到Service的數據資訊。

-----------------------------------分隔線-----------------------------------------------

Service功能主要是在後台處理一些比較耗時的操作,譬如說網路連接、資料下載、播放mp3...等等,所以用戶是看不到service的存在的,用戶只能透過Activity去對Service發送指令,Serviec接到指令後,就會去執行一些操作,所以Service不能夠與用戶做基本的溝通,這就是Service的特點

如何讓Activity能夠從Service那裏取的目前Service運行的狀態的基本使用法:

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="com.example.binderservice02.MainActivity" >

    <Button
        android:id="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="綁定Service" />

    <Button
        android:id="@+id/bt2"
        android:layout_below="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="發送請求" />

</RelativeLayout>

MainActivity.java:

public class MainActivity extends Activity {
private Button btn1;
private Button btn2;
private IBinder binder;

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

btn1 = (Button) findViewById(R.id.bt1);
btn2 = (Button) findViewById(R.id.bt2);
btn1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
//當點擊btn1會先綁定Activity和Service的binder關係
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
                                System.out.println("綁定binder");
}

});

btn2.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// 當點擊btn2馬上會調用SecondService的onTransact方法
//data是由Activity傳送過去的資料,reply是Service經由計算後傳回的資料,code和flags可設0
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInt(5);
try {
binder.transact(0, data, reply, 0);
int i = reply.readInt();
System.out.println("Activity的reply值是------>"+i);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
});
}

ServiceConnection conn = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName componentName,
IBinder binder) {
MainActivity.this.binder = binder;
}

@Override
public void onServiceDisconnected(ComponentName componentName) {

}

};

}
SecondService.java:

public class SecondService extends Service{

@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}

class MyBinder extends Binder {

@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {

int i = data.readInt(); //data是從Activity傳過來的
System.out.println("Service的data是 ----->" +i);

i = i +10;
reply.writeInt(i);

return super.onTransact(code, data, reply, flags);
}

}

}

Manifest.xml:

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

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".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>

印出結果:
08-23 13:05:50.217: I/System.out(16821): Service的data是 ----->5
08-23 13:05:50.217: I/System.out(16821): Activity的reply值是------>15












2015年8月18日 星期二

JSON中getString() 和optString()

The difference is that opt​​String returns the empty string ("") if the key you specify doesn't exist.getString on the other hand throws a JSONException. Use getString if it's an error for the data to be missing, or optString if you' re not sure if it will be there.



這個是在stackoverflow上面看到的,mark一下,簡單來說就是optString會在得不到你想要的值時候返回空字符串”“,而getString會拋出異常。

2015年8月12日 星期三

Fragment常用功能


1.切換Fragment

getFragmentManager().beginTransaction()
.addToBackStack(null)                        
.replace(R.id.container, fragment)    // 也可用.add(),差在原Fragment會不會觸發destory
.commit();


2.按下返回鍵會回到上一個Fragment
// 切換Fragment時,記得加上這個
.addToBackStack(null)  

// 在Activity中加入以下程式碼
@Override
public void onBackPressed() {
    FragmentManager fm = this.getFragmentManager();

    if (fm.getBackStackEntryCount() == 0) {
        this.finish();
    } else {
        fm.popBackStack();
    }
}

3.Fragment間溝通
public FragmentA extends Fragment {

    private void goToFragmentB() {
        Fragment fragment = new FragmentB();

        // 記得加上這句,讓FragmentB知道溝通的對象
        fragment.setTargetFragment(this, 0);    
        getFragmentManager()
                .beginTransaction()
                .add(R.id.container, fragment)
                .addToBackStack(null)
                .commit();
    }

    // 實作介面
    @Override
    public void doSomething() {
        // do something.
    }
}

public FragmentB extends Fragment implement Listener {

    private Listener mListener;

    // 定義溝通的介面
    public interface Listener() {
        public void doSomething();
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);       
        mListener= (Listener) getTargetFragment();
    }

    private void timeToDoSomething() {
        mListener.doSomething();
    }
}



2015年8月11日 星期二

Throwable

原處http://mrwlh.blog.51cto.com/2238823/1085526

ExceptionThrowable的一個主要子類。 Exception下面還有子類,其中一部分子類分別對應於Java程序運行時常

常遇到的各種異常的處理,其中包括隱式異常。比如,程序中除數為0引起的錯誤、數組下標越界錯誤等,這類異

常也稱為運行時異常,因為它們雖然是由程序本身引起的異常,但不是程序主動拋出的,而是在程序運行中產生

的。 Exception 子類下面的另一部分子類對應於Java程序中的非運行時異常的處理(在下圖中將它們直接屬於

Exception了),這些異常也稱為顯式異常。它們都是在程序中用語句拋出、並且也是用語句進行捕獲的,比如,

文件沒找到引起的異常、類沒找到引起的異常等。

一些主要子類對應的異常處理功能簡要說明如下:

ArithmeticException——由於除數為0引起的異常;

ArrayStoreException——由於數組存儲空間不夠引起的異常;

ClassCastException—一當把一個對象歸為某個類,但實際上此對象並不是由這個類創建的,也不是其子類創建

的,則會引起異常;

IllegalMonitorStateException——監控器狀態出錯引起的異常;

NegativeArraySizeException—一數組長度是負數,則產生異常;

NullPointerException—一程序試圖訪問一個空的數組中的元素或訪問空的對像中的方法或變量時產生異常;

OutofMemoryException——用new語句創建對象時,如係統無法為其分配內存空間則產生異常;

SecurityException——由於訪問了不應訪問的指針,使安全性出問題而引起異常;

IndexOutOfBoundsExcention——由於數組下標越界或字符串訪問越界引起異常;

IOException——由於文件未找到、未打開或者I/O操作不能進行而引起異常;

ClassNotFoundException——未找到指定名字的類或接口引起異常;

CloneNotSupportedException——一程序中的一個對象引用Object類的clone方法,但此對象並沒有連接Cloneable
接口,從而引起異常;

InterruptedException—一當一個線程處於等待狀態時,另一個線程中斷此線程,從而引起異常,有關線程的內容,

將在下一章講述;

NoSuchMethodException一所調用的方法未找到,引起異常;

Illega1AccessExcePtion—一試圖訪問一個非public方法;

StringIndexOutOfBoundsException——訪問字符串序號越界,引起異常;

ArrayIdexOutOfBoundsException—一訪問數組元素下標越界,引起異常;

NumberFormatException——字符的UTF代碼數據格式有錯引起異常;

IllegalThreadException—一線程調用某個方法而所處狀態不適當,引起異常;

FileNotFoundException——未找到指定文件引起異常;

EOFException——未完成輸入操作即遇文件結束引起異常。

2015年8月10日 星期一

setOnScrollListener() 簡介

http://123android.blogspot.tw/2013/01/setonscrolllistener.html

list.setOnScrollListener(new OnScrollListener(){
    @Override
    public void onScrollStateChanged(AbsListView absListView, int scrollState) {
        switch(scrollState) { 
            case SCROLL_STATE_FLING: 
                Log.i("Scroll State","滾動中...");
                break; 
            case SCROLL_STATE_IDLE: 
                Log.i("Scroll State","滾動停止...");
                break; 
            case SCROLL_STATE_TOUCH_SCROLL: 
                Log.i("Scroll State","手指滾動...");
                break; 
        }
    }

    @Override
    public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
              Log.i("OnScroll","Scroll");
        Log.i("OnScroll","firstVisibleItem:" + firstVisibleItem + " 最上面Item的編號");
        Log.i("OnScroll","visibleItemCount:" + visibleItemCount + " 你目前可以看到多少個 item");
        Log.i("OnScroll","totalItemCount:" + totalItemCount + " 你總共有多少個 Item");   
    }
});

listView_webview.setOnScrollListener(new OnScrollListener() {

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

switch (scrollState) {

// 当不滚动时

case OnScrollListener.SCROLL_STATE_IDLE:

// 判断滚动到底部

if (view.getLastVisiblePosition() == (view.getCount() - 1)) {

Log.i("--webview_over", "yes");



}

break;

}

}



@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {



}

});