天天看點

詳解使用者登入流程——Volley 請求

volley(一)基本特點

Google I/O 2013上,Volley釋出。它是Android平台上的網絡通信庫,能使網絡通信更快,更簡單,更健壯。
           

提供功能:

- JSON,圖像等的異步下載下傳;

- 網絡請求的排序(scheduling)

- 網絡請求的優先級處理

- 緩存

- 多級别取消請求

- 和Activity和生命周期的關聯(Activity結束時同時取消所有網絡請求)

volley适合:資料量不大,通信頻繁的網絡操作,對大資料量(下載下傳上傳檔案),會很糟糕。

使用者登入流程詳解 +volley(StringRequest)

在實習期間由于要求使用volley,是以第一次開始接觸volley,從一開始的迷茫陌生,到瘋狂的查找各種資料,通過在項目中用到的實際問題,我想做一些總結,是以寫了這篇文章。下面我将介紹我了解的使用者登入的一套詳細流程,涉及到volley請求以及json資料的解析。

登入流程的總結:首先通過EditText擷取到使用者名和密碼,然後再執行登入請求 LoginToServer()裡面發送使用者名和密碼,伺服器傳回給我json資料(如果用到Oauth 認證這裡傳回的json資料就應該是Token的一套東西,如果隻是簡單的登入,可以和伺服器約定傳回的内容,提取出對應的内容,包裝起來做判斷回報給使用者登入是否成功),我需要把這些json資料解析出來,然後再回報給使用者“登入成功”或者“登入失敗”。

LoginActivity.class這裡是在登入界面調用到 LoginToServer()這個方法,這裡我把 User_Local.class 裡面寫了基本的set,get方法,然後是裡面是全局(public static)的方法。

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.login_button:
                if (checkEdit()) {
                    //這裡記得一定要先get獲得資料
                    User_Local.setUsername(username.getText().toString());
                    User_Local.setPassword(password.getText().toString());
                  //  LoginToServer();
                    new LoginSupport(LoginActivity.this).LoginToServer();
                }
                break;
           

這裡是User_Local.class ,首先這裡為什麼要寫成public static,寫成這種是說這是全局變量。全局的引用方法就是類名直接引用,不用再new 一個對象。比如這裡就是引用直接就是上述的 User_Local.setUsername(username.getText().toString());。什麼時候用全局的,什麼時候不用,這個大家可以百度一下。比如在接受伺服器傳過來的json資料我要再建一套類去比對解析,這個時候就不要用全局的。

public class User_Local {

    public static String username = " " ;//使用者名
    public static String password =" ";//密碼

    public static String getUsername() {
        return username;
    }

    public static void setUsername(String username) {
       User_Local.username = username;
    }

    public static String getPassword() {
        return password;
    }

    public static void setPassword(String password) {
        User_Local.password = password;
    }
           

LoginSupport.class 這個類裡面我寫了volley的登入請求,還有伺服器傳回的json資料解析(這裡使用的是Gson來解析json資料),還有回報給使用者登入成功失敗與否

volley請求簡單說就三步:1.添加url位址。2.new 一個請求(請求裡面有成功和失敗的接口)3.添加請求到請求隊列裡面去

這裡我隻用了volley 裡面的StringRequest這個請求,這個請求向伺服器發送的應該是字元串吧,我了解的是這樣的。然後至于volley的其他請求大家可以參考其他的部落格和專業資料。

public void LoginToServer( ) {
        String url = "http://XXXXX";//1.這裡就是你要向伺服器發送請求的位址
        StringRequest loginRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {//2.new 一個請求
            @Override
            public void onResponse(String s) {//這裡是傳回正确回報的接口(隻要請求成功回報的資料都這這裡)
                //資料處理回報(可以這這裡處理伺服器傳回的資料)
                DealResponseFromServer(s);//json資料的解析和使用者回報
                Log.i("TAG",s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
            //volley 有專門處理error的庫,下面就是調用了其中的一些,可以友善調試的時候查找到錯誤
                Log.d(TAG, "Volley returned error________________:" + volleyError);
                Class klass = volleyError.getClass();
                if(klass == com.android.volley.AuthFailureError.class) {
                    Log.d(TAG,"AuthFailureError");
                    Toast.makeText(context,"未授權,請重新登入",Toast.LENGTH_LONG).show();
                } else if(klass == com.android.volley.NetworkError.class) {
                    Log.d(TAG,"NetworkError");
                    Toast.makeText(context,"網絡連接配接錯誤,請重新登入",Toast.LENGTH_LONG).show();
                } else if(klass == com.android.volley.NoConnectionError.class) {
                    Log.d(TAG,"NoConnectionError");
                } else if(klass == com.android.volley.ServerError.class) {
                    Log.d(TAG,"ServerError");
                    Toast.makeText(context,"伺服器未知錯誤,請重新登入",Toast.LENGTH_LONG).show();
                } else if(klass == com.android.volley.TimeoutError.class) {
                    Log.d(TAG,"TimeoutError");
                    Toast.makeText(context,"連接配接逾時,請重新登入",Toast.LENGTH_LONG).show();
                } else if(klass == com.android.volley.ParseError.class) {
                    Log.d(TAG,"ParseError");
                } else if(klass == com.android.volley.VolleyError.class) {
                    Log.d(TAG,"General error");
                }
                Toast.makeText(context,"登入失敗",Toast.LENGTH_LONG).show();
            }
        })
        {
            //這裡是添加請求頭的地方重寫了getHeaders() 方法(發送設麼請求頭要根據自己實際開發需要設定)
            @Override
            public Map<String, String> getHeaders()  {
                HashMap<String, String> header = new HashMap<String, String>();
                header.put("Accept","application/json");
                header.put("Content-Type","application/x-www-form-urlencoded");
                return header;
            }

            //這裡是發送參數的地方,重寫了 getParams() 方法(傳什麼參數給伺服器也是實際你自己修改)
             @Override
            protected Map<String, String> getParams() {
             HashMap<String, String> map = new HashMap<String, String>();

               //如果出現空指針異常或者是登入失敗,先檢查這裡有木有傳進來你要發送的使用者名和密碼。
               //是以在執行get資料方法之前一定要先存資料(set方法)
                map.put("username", User_Local.getUsername());
                map.put("password", User_Local.getPassword());
                return map;
            }
        };
        //設定逾時重新請求
        loginRequest.setRetryPolicy(new DefaultRetryPolicy(, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        //設定标簽,友善在stop(){}裡面取消對應的volley 請求
        loginRequest.setTag("POST");
        //3.把請求添加到全局請求隊列裡面
        MyApplication.getHttpQueue().add(loginRequest);
    }
           
//建立一個全局請求隊列
public class MyApplication extends Application {
    public static RequestQueue requestQueue;//

    @Override
    public void onCreate() {
        super.onCreate();
        requestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    public  static  RequestQueue getHttpQueue(){
        return requestQueue;
    }
}
           

Gson解析json資料的精華就是:

gson.fromJson(就是把json資料解析成普通資料)和gson.toJson(把普通資料轉化成json類型的資料格式)

要注意的是,這裡解析到伺服器的資料必須有一套模型和伺服器裡面的各種資料類型比對,也就是你需要根據傳過來的json資料建一個類來把解析的資料儲存起來。

//解析伺服器傳回的json字元串回報給使用者
    public void DealResponseFromServer(String s) {
        Gson gson = new Gson();//第一步,執行個體化
        User_Service user_service = gson.fromJson(s, User_Service.class);//第二步,解析資料
        if (s!=null) {//這裡的s就是上面成功回調接口裡面的參數
            //這裡我儲存了從伺服器傳回的token的資訊,至于token就涉及到oauth2.0的内容了,不懂得可以百度,
            //當然這裡可以保持你需要儲存的伺服器傳回的資料
            PreferenceUtils.setPrefString(context,User_Service.userKey, "access_token",  user_service.getAccess_token());//儲存令牌(這裡我用的是自己寫的一套SharedPreferences的工具類來儲存token)
            PreferenceUtils.setPrefString(context,User_Service.userKey, "refresh_token", user_service.getRefresh_token());//儲存重新整理令牌
            Toast.makeText(context, "登入成功", Toast.LENGTH_SHORT).show();//回報給使用者登入成功
        }
    }
           

這個就是用于接收伺服器傳回的json資料類型所建立的類,專門用于解析json資料的。這裡的變量就不用設定成全局的變量。

這裡面的關系我捋一下,1.從伺服器解析的json資料儲存到本地資料庫裡面2.然後本地需要調用資料的時候,再去資料庫裡面去取。

//用于接收解析伺服器傳回資料所給的資料
public class User_Service {
    public  static final String  userKey = "user_service";//用于儲存伺服器端傳回的資料檔案
    private  String access_token;//令牌
    private  String refresh_token;//重新整理令牌

    public String getAccess_token() {
        return access_token;
    }

    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }

    public void setRefresh_token(String refresh_token) {
        this.refresh_token = refresh_token;
    }

    public String getRefresh_token() {
        return refresh_token;
    }