關于Android實戰(zhàn)篇系列,一直不知從何入手寫。基本概念介紹對于實戰(zhàn)篇系列來講沒有太大意義,本系列一如SPRing實戰(zhàn)篇系列所倡導的理念一樣:知其然知其所以然,難點、疑點一網打盡(有點狂妄了)。還是決定從頭開始,這里對基本概念不做過多介紹,主要介紹使用。
一、背景知識
說到Activity,做Android的一點都不會陌生,真正項目開發(fā)中不止會用到Activity,而且會抽象出BaseActivity,其中處理公共部分(比如標題、回調函數等),具體部分還是有具體的Activity處理,這里也是利用了java中的設計模式——策略模式
二、BaseActivity配置
/** * 基本Activity,供其他Activity繼承,實現了回調及title設置、返回按鍵等 */public class BaseActivity extends Activity implements TextWatcher,RetrofitCallBack { protected ProgressDialog waitDialog; /** * 標記標題左右兩邊的類型:文字 */ protected final int TITLE_TYPE_TEXT = 0; /** * 標記標題左右兩邊的類型:圖片 */ protected final int TITLE_TYPE_IMG = 1; public Myapplication application; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); application = (MyApplication) getApplicationContext(); } @Override protected void onDestroy() { super.onDestroy(); dismissWaitDialog(); } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); // 判斷界面再次轉到前臺的時候,主題是否發(fā)生改變.如果改變了,則需要重新加載activity // this.recreate(); } @Override protected void onStop() { super.onStop(); } /** * 需在setContentView方法之后調用. 設置后,如果不對左側的事件進行監(jiān)聽,默認的點擊事件是結束當前界面. * <p> * 標題傳資源id和字符串皆可. * <p> * 如果某一側顯示的是圖片,則那一側只能傳對應的圖片資源id.如果是文字,則資源id和字符串皆可. * * @param title * 標題 * @param left * 是否顯示左側的部分 * @param leftType * 左側的類型 * @param l * 左側部分內容 * @param right * 是否顯示右側的部分 * @param rightType * 右側的類型 * @param r * 右側部分的內容 */ protected void setTitle(Object title, boolean left, int leftType, Object l, boolean right, int rightType, Object r) { try { TextView tvTitle = (TextView) findViewById(R.id.tv_title); TextView tvLeft = (TextView) findViewById(R.id.tv_title_left); LinearLayout llLeft = (LinearLayout) findViewById(R.id.ll_title_left); ImageView ivLeft = (ImageView) findViewById(R.id.iv_title_left); TextView tvRight = (TextView) findViewById(R.id.tv_title_right); ImageView ivRight = (ImageView) findViewById(R.id.iv_title_right); LinearLayout llRight = (LinearLayout) findViewById(R.id.ll_title_right); if (title != null && title instanceof String) { if (!TextUtils.isEmpty((String) title)) { tvTitle.setVisibility(View.VISIBLE); tvTitle.setText((String) title); } else { tvTitle.setVisibility(View.INVISIBLE); } } else if (title != null && title instanceof Integer) { if (((Integer) title) > 0) { tvTitle.setVisibility(View.VISIBLE); tvTitle.setText((Integer) title); } else { tvTitle.setVisibility(View.INVISIBLE); } } if (left) { llLeft.setVisibility(View.VISIBLE); if (leftType == TITLE_TYPE_TEXT) { ivLeft.setVisibility(View.GONE); tvLeft.setVisibility(View.VISIBLE); if (l instanceof String) { tvLeft.setText((String) l); } else if (l instanceof Integer) { tvLeft.setText((Integer) l); } } else if (leftType == TITLE_TYPE_IMG) { ivLeft.setVisibility(View.VISIBLE); tvLeft.setVisibility(View.GONE); if (l instanceof Integer) { ivLeft.setImageResource((Integer) l); } } } else { llLeft.setVisibility(View.INVISIBLE); } if (right) { llRight.setVisibility(View.VISIBLE); if (rightType == TITLE_TYPE_TEXT) { ivRight.setVisibility(View.GONE); tvRight.setVisibility(View.VISIBLE); if (r instanceof String) { tvRight.setText((String) r); } else if (r instanceof Integer) { tvRight.setText((Integer) r); } } else if (rightType == TITLE_TYPE_IMG) { ivRight.setVisibility(View.VISIBLE); tvRight.setVisibility(View.GONE); if (r instanceof Integer) { ivRight.setImageResource((Integer) r); } } } else { llRight.setVisibility(View.INVISIBLE); } } catch (Exception e) { } } /** * 設置點擊左上角的返回事件.默認是finish界面 */ protected void registerBack() { LinearLayout llLeft = (LinearLayout) findViewById(R.id.ll_title_left); llLeft.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { BaseActivity.this.finish(); } }); } /** * 設置點擊右上角的返回事件. */ protected void rightDo() { LinearLayout llRight = (LinearLayout) findViewById(R.id.ll_title_right); llRight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { rightDoWhat(); } }); } protected void rightDoWhat() { } // 封裝跳轉 public void openActivity(Class<?> c) { openActivity(c, null); } // 跳轉 傳遞數據 bundel public void openActivity(Class<?> c, Bundle b) { openActivity(c, b, null); } public void openActivity(Class<?> c, Bundle b, Uri uri) { Intent intent = new Intent(this, c); if (b != null) { intent.putExtras(b); } if (uri != null) { intent.setData(uri); } startActivity(intent); } /** * 跳轉登錄界面 */ protected void goLogin() { Intent intent = new Intent(this, LoginActivity.class); intent.putExtra(Constant.NEEDLOGIN, true); startActivityForResult(intent, 33); } /** * 全局等待對話框 */ public void showWaitDialog() { this.runOnUiThread(new Runnable() { @Override public void run() { if (waitDialog == null || !waitDialog.isShowing()) { waitDialog = new ProgressDialog(BaseActivity.this); waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); waitDialog.setCanceledOnTouchOutside(false); ImageView view = new ImageView(BaseActivity.this); view.setLayoutParams(new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); Animation loadAnimation = AnimationUtils.loadAnimation( BaseActivity.this, R.anim.rotate); view.startAnimation(loadAnimation); loadAnimation.start(); view.setImageResource(R.drawable.loading); // waitDialog.setCancelable(false); waitDialog.show(); waitDialog.setContentView(view); LogUtil.i("waitDialong......."); } } }); } public void dismissWaitDialog() { this.runOnUiThread(new Runnable() { @Override public void run() { if (waitDialog != null && waitDialog.isShowing()) { waitDialog.dismiss(); waitDialog = null; } } }); } /** * textWatcher的實現類,用于監(jiān)聽Editable的變化 * @param s * @param start * @param count * @param after */ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } /** * retrofitcallback方法實現,將response返回給Activity * @param response 返回數據 * @param method 回調方法標志 */ @Override public void onResponse(Response response, int method) { dismissWaitDialog(); } @Override public void onFailure(Response response, int method) { dismissWaitDialog(); } public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }}其中BaseActivity繼承了Activity(這個是必須滴,凡是Activity都要集成SDK中的Activity),實現了TextWatcher(監(jiān)聽Editable變化,后面會介紹),實現了RetrofitCallBack(retrofit的回調接口,這個在后面說道retrofit的時候會說明);除此之外,還設置了共用的title,返回鍵,openActivity,goLogin,等待對話框等。
三、BaseActivity的使用
下面以登錄界面為例,介紹BaseActivity的使用
1)先看界面
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grey_light" > <include android:id="@+id/title" android:layout_alignParentTop="true" layout="@layout/layout_stub_title" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/distanse60"> <EditText android:id="@+id/et_account" android:layout_width="match_parent" android:layout_height="@dimen/distanse50" android:background="@drawable/reg_input_bg2" android:drawableLeft="@drawable/phone" android:drawablePadding="@dimen/distanse10" android:hint="請輸入手機/用戶名" android:paddingLeft="@dimen/distanse15" android:paddingRight="@dimen/distanse10" android:textColor="@color/lightblack" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#ccc" /> <EditText android:id="@+id/et_pwd" android:layout_width="match_parent" android:layout_height="@dimen/distanse50" android:background="@drawable/reg_input_bg2" android:drawableLeft="@drawable/passWord" android:drawablePadding="@dimen/distanse10" android:hint="登錄密碼" android:inputType="textPassword" android:paddingLeft="@dimen/distanse15" android:paddingRight="@dimen/distanse10" android:textColor="@color/lightblack" /> <TextView android:id="@+id/tv_sure" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/distanse10" android:layout_marginRight="@dimen/distanse10" android:layout_marginTop="@dimen/distanse50" android:padding="@dimen/distanse10" android:background="@drawable/buttonstyle" android:enabled="false" android:gravity="center" android:text="確定" android:textColor="@color/white" android:textSize="@dimen/text_size16" /> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_reset" android:layout_width="match_parent" android:layout_height="@dimen/distanse40" android:layout_marginLeft="@dimen/distanse15" android:layout_marginRight="@dimen/distanse15" android:layout_marginTop="@dimen/distanse10" android:drawablePadding="@dimen/distanse5" android:gravity="right" android:text="忘記密碼" android:textColor="@color/light_blue" android:textSize="@dimen/text_size15" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="@dimen/distanse10"> <TextView android:id="@+id/tv_reg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:padding="@dimen/distanse10" android:text="還沒有賬號?現在注冊" android:textColor="@color/light_blue" android:textSize="@dimen/text_size14" android:layout_weight="1" /> </LinearLayout> </LinearLayout></RelativeLayout>

其中引入了共用title布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_title" android:layout_width="match_parent" android:layout_height="44dp" android:background="@color/blue1" android:gravity="center_vertical" > <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_toLeftOf="@+id/ll_title_right" android:layout_toRightOf="@+id/ll_title_left" android:ellipsize="end" android:gravity="center" android:text="New Text" android:textColor="@color/white" android:textSize="20sp" /> <LinearLayout android:id="@+id/ll_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:gravity="center_vertical|left" android:minWidth="80dp" android:orientation="horizontal" > <ImageView android:id="@+id/iv_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:paddingLeft="10dp" android:paddingRight="10dp" android:src="@drawable/to_left" /> <TextView android:id="@+id/tv_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center_vertical|left" android:paddingLeft="10dp" android:paddingRight="10dp" android:text="New Text" android:textColor="@color/white" android:textSize="16sp" android:visibility="gone" /> </LinearLayout> <LinearLayout android:id="@+id/ll_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:gravity="center_vertical|right" android:minWidth="80dp" android:orientation="horizontal" > <ImageView android:id="@+id/iv_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:paddingLeft="10dp" android:paddingRight="10dp" android:src="@drawable/to_left" /> <TextView android:id="@+id/tv_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center_vertical|right" android:paddingRight="10dp" android:text="New Text" android:textColor="@color/white" android:textSize="16sp" android:visibility="gone" /> </LinearLayout></RelativeLayout>2)LoginActivity
public class LoginActivity extends BaseActivity { @BindView(R.id.et_account) EditText etAccount; @BindView(R.id.et_pwd) EditText etPwd; @BindView(R.id.tv_reg) TextView tvReg; @BindView(R.id.tv_sure) TextView tvSure; private String account, pwd, userId, password; private boolean needLogin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_login); //set布局 ButterKnife.bind(this); setTitle(R.string.login, true, TITLE_TYPE_IMG, R.drawable.to_left, true, TITLE_TYPE_TEXT, ""); //基類方法,設置title initView(); initData(); } private void initView() { registerBack(); //設置text變化監(jiān)聽器 etAccount.addTextChangedListener(this); etPwd.addTextChangedListener(this); tvReg.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);// 下劃線 } /** * 根據是否輸入值,判斷是否顯示確定按鈕 * @param s */ @Override public void afterTextChanged(Editable s) { super.afterTextChanged(s); String userStr = etAccount.getText().toString(); String pwdStr = etPwd.getText().toString(); if(userStr.length() * pwdStr.length() != 0){ tvSure.setEnabled(true); }else{ tvSure.setEnabled(false); } } private void initData() { account = application.getUserinfobean().getPhoneNumber(); if (!StringUtil.isEmpty(account)) { etAccount.setText(account); } Intent intent = getIntent(); if (intent.hasExtra(Constant.NEEDLOGIN)) { needLogin = intent.getBooleanExtra(Constant.NEEDLOGIN, false); } } @OnClick({R.id.tv_sure, R.id.tv_reset, R.id.tv_reg}) public void onClick(View view) { account = etAccount.getText() + ""; switch (view.getId()) { case R.id.tv_sure: pwd = etPwd.getText() + ""; if (StringUtil.isEmpty(account)) { ToastUtil.makeShortText(this, "請輸入登錄賬號"); return; } if (StringUtil.isEmpty(pwd)) { ToastUtil.makeShortText(this, "請輸入登錄密碼"); return; } if (pwd.length() < 6 || pwd.length() > 16) { ToastUtil.makeShortText(this, "密碼不能小于6位或大于16位"); return; } getUserById(account); break; case R.id.tv_reg: openActivity(RegisterActivity.class); break; case R.id.tv_reset: openActivity(ResetPwdActivity.class); break; default: break; } } private void getLogin(String userId, String password, String loginType) { showWaitDialog(); Map<String, Object> signMap = new HashMap<String, Object>(); signMap.put("name", userId); signMap.put("pwd", password); signMap.put("loginType", loginType); Map<String, String> reqMap = SignUtil.jsonmd5(signMap); RetrofitHttpRequest.addToEnqueue(RetrofitHttpRequest.getInstance().mHttpService.login(reqMap), this, HttpStaticApi.HTTP_LOGIN); } /** * 根據用戶名獲取userId,加密用md5(userId+pwd) */ private void getUserById(String name) { showWaitDialog(); Map<String, Object> signMap = new HashMap<String, Object>(); signMap.put("name", name); Map<String, String> reqMap = SignUtil.jsonMd5(signMap); RetrofitHttpRequest.addToEnqueue(RetrofitHttpRequest.getInstance().mHttpService.getUserById(reqMap), this, HttpStaticApi.HTTP_GETUSERBYID); } @Override public void onResponse(Response response, int method) { super.onResponse(response, method); switch (method) { case HttpStaticApi.HTTP_GETUSERBYID: UserIdBean userIdBean = (UserIdBean) response.body(); UserIdBean.ResDataBean resDataBean = userIdBean.getResData(); if (HttpConst.STATUS_SUC.equals(resDataBean.getStatus())) { userId = resDataBean.getData(); password = StringUtil.md5(userId + pwd); LogUtil.e(password); getLogin(account, password, "1"); } else { ToastUtil.makeShortText(this, resDataBean.getMessage()); } break; case HttpStaticApi.HTTP_LOGIN: UserBean userBean = (UserBean) response.body(); UserBean.ResDataBean resDataBean1 = userBean.getResData(); if (HttpConst.STATUS_SUC.equals(resDataBean1.getStatus())) { UserBean.ResDataBean.DataBean dataBean = resDataBean1.getData(); Bundle bundle = new Bundle(); bundle.putString("user_id", userId); bundle.putString("user_name", dataBean.getCustomerName()); bundle.putString("phone", dataBean.getMobile()); bundle.putString("nickName", dataBean.getNickName()); bundle.putString("email", dataBean.getEmail()); bundle.putBoolean("isBinding", dataBean.getIsbinding().equals("1") ? true : false); application.getUserinfobean().setaccess(bundle); //從需要登錄頁跳轉的返回目標頁,直接點擊登錄的跳轉首頁 if (!needLogin){ openActivity(MainActivity.class); } finish(); } else { ToastUtil.makeShortText(this, "登錄失敗" + resDataBean1.getMessage()); } break; default: break; } }后面retrofit相關是和服務器通信的,這個后面會有專題介紹。還看到控件的獲取和點擊事件的設置用了Butterknife,@BindView和@OnClick,這個將在下一章進行介紹Butterknife的使用
四、AndroidManifest.xml
當然不要忘了在AndroidManifest.xml進行設置,否則無法啟動
<activity android:name="com.xxx.xxx.login.LoginActivity" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan|stateHidden" />運行效果圖

新聞熱點
疑難解答