Android实战----从Activity入手(编写BaseActivity)

Posted Herman-Hong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实战----从Activity入手(编写BaseActivity)相关的知识,希望对你有一定的参考价值。

关于android实战篇系列,一直不知从何入手写。基本概念介绍对于实战篇系列来讲没有太大意义,本系列一如Spring实战篇系列所倡导的理念一样:知其然知其所以然,难点、疑点一网打尽(有点狂妄了)。还是决定从头开始,这里对基本概念不做过多介绍,主要介绍使用。

一、背景知识

说到Activity,做Android的一点都不会陌生,真正项目开发中不止会用到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();
		// 判断界面再次转到前台的时候,主题是否发生改变.如果改变了,则需要重新加载activity
		// this.recreate();

	

	@Override
	protected void onStop() 
		super.onStop();
	

	/**
	 * 需在setContentView方法之后调用. 设置后,如果不对左侧的事件进行监听,默认的点击事件是结束当前界面.
	 * <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的实现类,用于监听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(监听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变化监听器
        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" />


运行效果图





以上是关于Android实战----从Activity入手(编写BaseActivity)的主要内容,如果未能解决你的问题,请参考以下文章

实战|Android后台启动Activity实践之路续

Android从xml加载到View对象过程解析

Android项目实战(三十七):Activity管理及BaseActivity的实现

Android实战——Activity超详细学习笔记

Android项目实战:Dialog主题Activity实现自定义对话框效果

Android实战开发篇 监听广播唤起Activity(活动)Dialog弹窗的方案