项目优化-BaseActivity和BaseFragment

明眼人一看便知,直接上代码:

BaseActivity

package com.laundrylangpickcargo.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;

import com.handmark.pulltorefresh.library.ILoadingLayout;
import com.handmark.pulltorefresh.library.PullToRefreshAdapterViewBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.laundrylangpickcargo.constant.ConstantValue;
import com.laundrylangpickcargo.fragment.BaseFragment;
import com.laundrylangpickcargo.mai.BaseApplication;
import com.laundrylangpickcargo.mai.R;
import com.laundrylangpickcargo.util.ActivityUtils;
import com.laundrylangpickcargo.util.DoubleClickExitDetector;
import com.laundrylangpickcargo.util.ForbadClick;
import com.laundrylangpickcargo.util.Memmaker;
import com.laundrylangpickcargo.util.PreferencesUtil;
import com.laundrylangpickcargo.util.SystemService;
import com.laundrylangpickcargo.util.TitleBuilder;
import com.laundrylangpickcargo.util.ToastUtils;
import com.laundrylangpickcargo.util.TypefaceUtil;
import com.laundrylangpickcargo.view.LogoProgressDialog;
import com.umeng.analytics.MobclickAgent;

import butterknife.ButterKnife;
import butterknife.Unbinder;

public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener, View.OnLongClickListener, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, PullToRefreshBase.OnRefreshListener2<ListView> {
    protected Resources res;
    protected BaseApplication baseApp;
    private LogoProgressDialog loadDialog;
    private NetworkChangeReceiver networkChangeReceiver;
    private TypefaceChangeReceiver typefaceChangeReceiver;
    protected TitleBuilder titleBuilder;
    private DoubleClickExitDetector exitDetector;
    private Unbinder unbinder;
    public LayoutInflater layoutInflater;

    protected enum NetState {
        WIFI, MOBILE
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayout());
        //改变新创建Activity的字体
        //在改变字体发送广播的地方添加代码:PreferencesUtil.put(ConstantValue.AppSetting.SHPNAME, ConstantValue.AppSetting.typeface, typeface);
        onTypefaceChange(PreferencesUtil.getString(ConstantValue.AppSetting.SHPNAME, ConstantValue.AppSetting.typeface));
        if (null != getIntent()) {
            handleIntent(getIntent());
        }

        networkChangeReceiver = new NetworkChangeReceiver();
        IntentFilter networkFilter = new IntentFilter();
        networkFilter.addAction(ConstantValue.Action.NETWORK_ACTION);
        registerReceiver(networkChangeReceiver, networkFilter);

        typefaceChangeReceiver = new TypefaceChangeReceiver();
        IntentFilter typefaceFilter = new IntentFilter();
        typefaceFilter.addAction(ConstantValue.Action.TYPEFACE_ACTION);
        registerReceiver(typefaceChangeReceiver, typefaceFilter);

        unbinder = ButterKnife.bind(this);
        res = this.getApplicationContext().getResources();
        baseApp = (BaseApplication) this.getApplication();
        layoutInflater = SystemService.getLayoutInflater(this);
        this.getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        loadDialog = new LogoProgressDialog(this);
        titleBuilder = new TitleBuilder(this);
        titleBuilder.setTitleText(res.getString(R.string.app_name));
        exitDetector = new DoubleClickExitDetector(this);

        config();
        initView();
        setListener();

        ActivityUtils.addActivity(this);
    }

    @Override
    public void onBackPressed() {
        if (ActivityUtils.getSurvivalNumber() == 1) {
            if (exitDetector.click()) {
                removeFragment();
                ActivityUtils.exitAllActivity();
            }
        } else {
            removeFragment();
            super.onBackPressed();
        }
    }

    @Override
    protected void onPause() {
        // (仅有Activity的应用中SDK自动调用,不需要单独写)保证 onPageEnd 在onPause 之前调用,因为 onPause 中会保存信息。
        MobclickAgent.onPageEnd(getClass().getSimpleName());
        MobclickAgent.onPause(this);
        super.onPause();
    }

    @Override
    protected void onResume() {
        //统计页面(仅有Activity的应用中SDK自动调用,不需要单独写。
        MobclickAgent.onPageStart(getClass().getSimpleName());
        //统计时长
        MobclickAgent.onResume(this);
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        unbinder.unbind();
        loadDialog.dismiss();
        unregisterReceiver(networkChangeReceiver);
        unregisterReceiver(typefaceChangeReceiver);
        ActivityUtils.finishActivity(this);
        Memmaker.release(this);
        super.onDestroy();
    }

    /**
     * 处理intent,第一个被调用,不要做关于view的操作
     *
     * @param intent 从上个页面传过来的intent,不必非空判断
     */
    protected abstract void handleIntent(Intent intent);

    /**
     * 注册监听,对象声明,初始化等
     */
    protected abstract void config();

    /**
     * 获取布局下的view
     */
    protected abstract void initView();

    /**
     * 设置view的监听器
     */
    protected abstract void setListener();

    /**
     * 设置当前activity的layout
     *
     * @return 当前界面的布局id
     */
    protected abstract int getLayout();

    /**
     * 获得布局中fragment
     *
     * @return 当前页面中fragment的布局id
     */
    protected abstract int getFragmentId();

    /**
     * 设置当前activity的软键盘方式
     *
     * @param mode
     */
    protected void setSoftInputMode(int mode) {
//        WindowManager.LayoutParams.
//        SOFT_INPUT_ADJUST_NOTHING:         不调整(输入法完全直接覆盖住,未开放此参数)
//        SOFT_INPUT_ADJUST_PAN:                 把整个Layout顶上去露出获得焦点的EditText,不压缩多余空间
//        SOFT_INPUT_ADJUST_RESIZE:            整个Layout重新编排,重新分配多余空间
//        SOFT_INPUT_ADJUST_UNSPECIFIED:  系统自己根据内容自行选择上两种方式的一种执行(默认配置)
        this.getWindow().setSoftInputMode(mode);
    }

    /**
     * 添加fragment
     */
    public void addFragment(BaseFragment fragment) {
        if (fragment != null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(getFragmentId(), fragment, fragment.getClass().getSimpleName())
                    .addToBackStack(fragment.getClass().getSimpleName())
                    .commitAllowingStateLoss();
        }
    }

    /**
     * 移除fragment
     */
    public void removeFragment() {
        if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
            getSupportFragmentManager().popBackStack();
        } else {
            finish();
        }
    }

    /**
     * @param pullView
     * @return
     */
    protected PullToRefreshAdapterViewBase pullViewSetting(PullToRefreshAdapterViewBase pullView) {
        return pullViewSetting(pullView,null);
    }

    /**
     * @param pullView
     * @return
     */
    protected PullToRefreshAdapterViewBase pullViewSetting(PullToRefreshAdapterViewBase pullView,View headView) {
        ILoadingLayout startLabels = pullView.getLoadingLayoutProxy(true, false);
        startLabels.setPullLabel(ConstantValue.PullDownLabel);// 刚下拉时,显示的提示
        startLabels.setRefreshingLabel(ConstantValue.RefreshingLabel);// 刷新时
        startLabels.setReleaseLabel(ConstantValue.ReleaseLabel);// 下来达到一定距离时,显示的提示

        ILoadingLayout endLabels = pullView.getLoadingLayoutProxy(false, true);
        endLabels.setPullLabel(ConstantValue.PullUpLabel);// 刚上拉时,显示的提示
        endLabels.setRefreshingLabel(ConstantValue.RefreshingLabel);// 刷新时
        endLabels.setReleaseLabel(ConstantValue.ReleaseLabel);// 下来达到一定距离时,显示的提示

        pullView.setMode(PullToRefreshBase.Mode.BOTH);
        pullView.setOnRefreshListener(this);

        if(headView!=null) {
            View refreshableView = pullView.getRefreshableView();
            if(refreshableView instanceof ListView){
                ListView listView = (ListView) refreshableView;
                listView.addHeaderView(headView);
            }
        }
        return pullView;
    }

    protected void showLoading() {
        if (loadDialog != null)
            loadDialog.show();
    }

    protected void hideLoading() {
        if (loadDialog != null)
            loadDialog.dismiss();
    }

    /**
     * showToast
     *
     * @param status 吐司的提示信息
     */
    protected void showToast(String status) {
        ToastUtils.showToast(this, status);
    }

    @Override
    public void onClick(View v) {
        if (ForbadClick.isFastDoubleClick(v)) {
            return;
        }
    }

    @Override
    public boolean onLongClick(View v) {
        return false;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        //消费事件,不往下传递,return false则会继续执行onItemClick
        return true;
    }

    @Override
    public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
    }

    @Override
    public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
    }

    /**
     * 网络已连接
     *
     * @param type 1:数据 2.无线
     */
    protected void onNetworkConnect(NetState type) {
    }

    /**
     * 网络中断
     */
    protected void onNetworkInterrupt() {
    }

    /**
     * 字体改变
     */
    protected void onTypefaceChange(String typeface) {
        TypefaceUtil.replaceFont(this, typeface);
    }

    /**
     * 网络状态监听器
     */
    private class NetworkChangeReceiver extends BroadcastReceiver {
        NetworkInfo.State wifiState = null;
        NetworkInfo.State mobileState = null;

        @Override
        public void onReceive(Context context, Intent intent) {
            if (ConstantValue.Action.NETWORK_ACTION.equals(intent.getAction())) {
                //获取手机的连接服务管理器,这里是连接管理器类
                ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
                mobileState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();

                if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED != wifiState && NetworkInfo.State.CONNECTED == mobileState) {
                    onNetworkConnect(NetState.MOBILE);
                } else if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED == wifiState && NetworkInfo.State.CONNECTED != mobileState) {
                    onNetworkConnect(NetState.WIFI);
                } else if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED != wifiState && NetworkInfo.State.CONNECTED != mobileState) {
                    onNetworkInterrupt();
                }
            }
        }
    }

    /**
     * 字体改变监听,用于改变整个APP字体
     */
//    Intent intent = new Intent(ConstantValue.ReceiverAction.TYPEFACE_ACTION);
//    String typeface = "fonts/xxx.ttf";
//    intent.putExtra("typeface", typeface);
//    sendBroadcast(intent);
    private class TypefaceChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ConstantValue.Action.TYPEFACE_ACTION.equals(intent.getAction())) {
                String typeface = intent.getStringExtra("typeface");
                //改变未销毁尚存在的Activity的字体
                onTypefaceChange(typeface);
            }
        }
    }
}

BaseFragment

package com.laundrylangpickcargo.fragment;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import com.handmark.pulltorefresh.library.ILoadingLayout;
import com.handmark.pulltorefresh.library.PullToRefreshAdapterViewBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.laundrylangpickcargo.activity.BaseActivity;
import com.laundrylangpickcargo.constant.ConstantValue;
import com.laundrylangpickcargo.mai.BaseApplication;
import com.laundrylangpickcargo.util.ForbadClick;
import com.laundrylangpickcargo.util.Memmaker;
import com.laundrylangpickcargo.util.PreferencesUtil;
import com.laundrylangpickcargo.util.SystemService;
import com.laundrylangpickcargo.util.ToastUtils;
import com.laundrylangpickcargo.util.TypefaceUtil;
import com.laundrylangpickcargo.view.LogoProgressDialog;
import com.umeng.analytics.MobclickAgent;

import butterknife.ButterKnife;
import butterknife.Unbinder;

public abstract class BaseFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener,AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener,PullToRefreshBase.OnRefreshListener2<ListView>, TextView.OnEditorActionListener {

    protected Resources res;
    protected BaseApplication baseApp;
    protected BaseActivity holdActivity;
    private LogoProgressDialog loadDialog;
    private NetworkChangeReceiver networkChangeReceiver;
    private TypefaceChangeReceiver typefaceChangeReceiver;
    private Unbinder unbinder;
    public LayoutInflater layoutInflater;

    protected enum NetState {
        WIFI, MOBILE
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.holdActivity = (BaseActivity) context;

        res = holdActivity.getApplicationContext().getResources();
        baseApp = (BaseApplication) holdActivity.getApplication();
        layoutInflater = SystemService.getLayoutInflater(holdActivity);

        loadDialog = new LogoProgressDialog(holdActivity);
        networkChangeReceiver = new NetworkChangeReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConstantValue.Action.NETWORK_ACTION);
        holdActivity.registerReceiver(networkChangeReceiver, intentFilter);

        typefaceChangeReceiver = new TypefaceChangeReceiver();
        IntentFilter typefaceFilter = new IntentFilter();
        typefaceFilter.addAction(ConstantValue.Action.TYPEFACE_ACTION);
        holdActivity.registerReceiver(typefaceChangeReceiver, typefaceFilter);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(getLayout(), container, false);
        //改变新创建Activity的字体
        //在改变字体发送广播的地方添加代码:PreferencesUtil.put(ConstantValue.AppSetting.SHPNAME, ConstantValue.AppSetting.typeface, typeface);
        onTypefaceChange(PreferencesUtil.getString(ConstantValue.AppSetting.SHPNAME, ConstantValue.AppSetting.typeface));
        if (null != getArguments()) {
            handleBundle(getArguments());
        }

        unbinder = ButterKnife.bind(this, view);

        config();
        initView(view);
        setListener();
        return view;
    }

    @Override
    public void onResume() {
        //统计页面
        MobclickAgent.onPageStart(getClass().getSimpleName());
        super.onResume();
    }

    @Override
    public void onPause() {
        MobclickAgent.onPageEnd(getClass().getSimpleName());
        super.onPause();
    }

    @Override
    public void onDetach() {
        unbinder.unbind();
        loadDialog.dismiss();
        holdActivity.unregisterReceiver(networkChangeReceiver);
        holdActivity.unregisterReceiver(typefaceChangeReceiver);
        Memmaker.release(this);
        super.onDetach();
    }

    /**
     * 处理bundle,第一个被调用,不要做关于view的操作
     *
     * @param bundle 从宿主传过来的bundle,不必非空判断
     */
    protected abstract void handleBundle(Bundle bundle);

    /**
     * 注册监听,对象声明,初始化等
     */
    protected abstract void config();

    /**
     * 获取布局下的view
     *
     * @param view 当前fragment的布局view对象
     */
    protected abstract void initView(View view);

    /**
     * 设置view的监听器
     */
    protected abstract void setListener();

    /**
     * 设置当前fragment的layout
     *
     * @return 当前界面的布局id
     */
    protected abstract int getLayout();

    //获取宿主Activity
    protected BaseActivity getHoldingActivity() {
        return holdActivity;
    }

    //添加fragment
    protected void addFragment(BaseFragment fragment) {
        if (null != fragment) {
            getHoldingActivity().addFragment(fragment);
        }
    }

    //移除fragment
    protected void removeFragment() {
        getHoldingActivity().removeFragment();
    }

    /**
     * @param pullView
     * @return
     */
    protected PullToRefreshAdapterViewBase pullViewSetting(PullToRefreshAdapterViewBase pullView) {
        return pullViewSetting(pullView,null);
    }

    /**
     * @param pullView
     * @return
     */
    protected PullToRefreshAdapterViewBase pullViewSetting(PullToRefreshAdapterViewBase pullView,View headView) {
        ILoadingLayout startLabels = pullView.getLoadingLayoutProxy(true, false);
        startLabels.setPullLabel(ConstantValue.PullDownLabel);// 刚下拉时,显示的提示
        startLabels.setRefreshingLabel(ConstantValue.RefreshingLabel);// 刷新时
        startLabels.setReleaseLabel(ConstantValue.ReleaseLabel);// 下来达到一定距离时,显示的提示

        ILoadingLayout endLabels = pullView.getLoadingLayoutProxy(false, true);
        endLabels.setPullLabel(ConstantValue.PullUpLabel);// 刚上拉时,显示的提示
        endLabels.setRefreshingLabel(ConstantValue.RefreshingLabel);// 刷新时
        endLabels.setReleaseLabel(ConstantValue.ReleaseLabel);// 下来达到一定距离时,显示的提示

        pullView.setMode(PullToRefreshBase.Mode.BOTH);
        pullView.setOnRefreshListener(this);

        if(headView!=null) {
            View refreshableView = pullView.getRefreshableView();
            if(refreshableView instanceof ListView){
                ListView listView = (ListView) refreshableView;
                listView.addHeaderView(headView);
            }
        }
        return pullView;
    }

    protected void showLoading() {
        if (loadDialog != null)
            loadDialog.show();
    }

    protected void hideLoading() {
        if (loadDialog != null)
            loadDialog.dismiss();
    }

    /**
     * showToast
     *
     * @param status 吐司的提示信息
     */
    protected void showToast(String status) {
        ToastUtils.showToast(holdActivity, status);
    }

    @Override
    public void onClick(View v) {
        if(ForbadClick.isFastDoubleClick(v)){return;}
    }

    @Override
    public boolean onLongClick(View v) {
        return false;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        //消费事件,不往下传递,return false则会继续执行onItemClick
        return true;
    }

    @Override
    public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
    }

    @Override
    public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_SEARCH) {
            onEditorActionSearch();
            return true;
        }
        return false;
    }

    public void onEditorActionSearch() {
    }

    /**
     * 网络已连接
     *
     * @param type 1:数据 2.无线
     */
    protected void onNetworkConnect(NetState type) {
    }

    /**
     * 网络中断
     */
    protected void onNetworkInterrupt() {
    }

    /**
     * 字体改变
     */
    protected void onTypefaceChange(String typeface){
        TypefaceUtil.replaceFont(holdActivity, typeface);
    }

    /**
     * 网络状态监听器
     */
    public class NetworkChangeReceiver extends BroadcastReceiver {
        NetworkInfo.State wifiState = null;
        NetworkInfo.State mobileState = null;

        @Override
        public void onReceive(Context context, Intent intent) {
            if (ConstantValue.Action.NETWORK_ACTION.equals(intent.getAction())) {
                //获取手机的连接服务管理器,这里是连接管理器类
                ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                wifiState = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
                mobileState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();

                if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED != wifiState && NetworkInfo.State.CONNECTED == mobileState) {
                    onNetworkConnect(NetState.MOBILE);
                } else if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED == wifiState && NetworkInfo.State.CONNECTED != mobileState) {
                    onNetworkConnect(NetState.WIFI);
                } else if (wifiState != null && mobileState != null && NetworkInfo.State.CONNECTED != wifiState && NetworkInfo.State.CONNECTED != mobileState) {
                    onNetworkInterrupt();
                }
            }
        }
    }

    /**
     * 字体改变监听,用于改变整个APP字体
     */
//    Intent intent = new Intent(ConstantValue.ReceiverAction.TYPEFACE_ACTION);
//    String typeface = "fonts/xxx.ttf";
//    intent.putExtra("typeface", typeface);
//    sendBroadcast(intent);
    private class TypefaceChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(ConstantValue.Action.TYPEFACE_ACTION.equals(intent.getAction())){
                String typeface = intent.getStringExtra("typeface");
                //改变未销毁尚存在的Activity的字体
                onTypefaceChange(typeface);
            }
        }
    }
}

几个关键类:

DoubleClickExitDetector.java
package com.laundrylangpickcargo.util;/*
 * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.content.Context;
import android.widget.Toast;

import java.util.Locale;

/**
 * 双击退出识别器
 */
public class DoubleClickExitDetector {
    public static String DEFAULT_HINT_MESSAGE_CHINA = "再按一次退出程序";
    public static String DEFAULT_HINT_MESSAGE_OTHER = "Press again to exit the program";
    private int effectiveIntervalTime;  // 有效的间隔时间,单位毫秒
    private long lastClickTime; // 上次点击时间
    private String hintMessage; // 提示消息
    private Context context;

    /**
     * 创建一个双击退出识别器
     * @param context Androdi上下文
     * @param hintMessage 提示消息
     * @param effectiveIntervalTime 有效间隔时间
     */
    public DoubleClickExitDetector(Context context, String hintMessage, int effectiveIntervalTime) {
        this.context = context;
        this.hintMessage = hintMessage;
        this.effectiveIntervalTime = effectiveIntervalTime;
    }

    /**
     * 创建一个双击退出识别器,有效间隔时间默认为2000毫秒
     * @param context Androdi上下文
     * @param hintContent 提示消息
     */
    public DoubleClickExitDetector(Context context, String hintContent) {
        this(context, hintContent, 2000);
    }

    /**
     * 创建一个双击退出识别器,中国环境下默认提示消息为“再按一次退出程序”,其它环境下默认提示消息为“Press again to exit the program”;有效间隔时间默认为2000毫秒
     * @param context Androdi上下文
     */
    public DoubleClickExitDetector(Context context) {
        this(context, Locale.CHINA.equals(Locale.getDefault()) ? DEFAULT_HINT_MESSAGE_CHINA : DEFAULT_HINT_MESSAGE_OTHER, 2000);
    }

    /**
     * 点击,你需要重写Activity的onBackPressed()方法,先调用此方法,如果返回true就执行父类的onBackPressed()方法来关闭Activity否则不执行
     * @return 当两次点击时间间隔小于有效间隔时间时就会返回true,否则返回false
     */
    public boolean click(){
        long currentTime = System.currentTimeMillis();
        boolean result = (currentTime-lastClickTime) < effectiveIntervalTime;
        lastClickTime = currentTime;
        if(!result){
            Toast.makeText(context, hintMessage, Toast.LENGTH_SHORT).show();
        }
        return result;
    }

    /**
     * 设置有效间隔时间,单位毫秒
     * @param effectiveIntervalTime 效间隔时间,单位毫秒。当两次点击时间间隔小于有效间隔时间click()方法就会返回true
     */
    public void setEffectiveIntervalTime(int effectiveIntervalTime) {
        this.effectiveIntervalTime = effectiveIntervalTime;
    }

    /**
     * 设置提示消息
     * @param hintMessage 当前点击同上次点击时间间隔大于有效间隔时间click()方法就会返回false,并且显示提示消息
     */
    public void setHintMessage(String hintMessage) {
        this.hintMessage = hintMessage;
    }
}
ForbadClick.java
package com.laundrylangpickcargo.util;

import android.view.View;

/**
 * 是否快速双击
 */
public class ForbadClick {

    private static long lastClickTime;
    private static View view;
    public static boolean isFastDoubleClick(View v) {
        long time = System.currentTimeMillis();     
        if ( view == v && time - lastClickTime < 3000) {
            return true;     
        }
        view = v;
        lastClickTime = time;     
        return false;     
    }
    public static boolean isFastDoubleClick() {
        long time = System.currentTimeMillis();
        if ( time - lastClickTime < 3000) {
            return true;
        }
        lastClickTime = time;
        return false;
    }
}
Memmaker.java
package com.laundrylangpickcargo.util;

import java.lang.reflect.Field;

/**
 * Created by Sinaan on 2016/10/21.
 * 内存优化管理工具
 */
public class Memmaker {
    /**
     * 释放(置null)当前类声明的属性或对象
     * 调用:
     * Memmaker.release(this)或
     * Memmaker.release(obj.getClass())
     * @param obj this
     */
    public static void release(Object obj){
        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for(Field field:fields){
                field.setAccessible(true);
                field.set(obj, null);
            }
        } catch (Exception e) {
        }finally{
            try {
                Field[] fields = obj.getClass().getSuperclass().getDeclaredFields();
                for(Field field:fields){
                    field.setAccessible(true);
                    field.set(obj, null);
                }
            } catch (Exception e) {
            }
        }
        System.gc();
    }

}
TitleBuilder.java
package com.laundrylangpickcargo.util;

import android.app.Activity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.laundrylangpickcargo.constant.ConstantValue;
import com.laundrylangpickcargo.mai.R;

/**
 * Created by Sinaan on 2016/10/20.
 * 标题栏统一设置
 */
public class TitleBuilder {
    private ImageView ivtoolbarleft;
    private TextView tvtoolbarleft;
    private LinearLayout rltoolbarleft;
    private TextView tvtoolbarcenter;
    private RelativeLayout rltoolbarcenter;
    private ImageView ivtoolbarright;
    private TextView tvtoolbarright;
    private RelativeLayout rltoolbarright;
    private LinearLayout lltoolbar;
    private View view;
    private boolean isLinearLayout;

    public TitleBuilder(final Activity context) {
        View root = TypefaceUtil.getRootView(context);
        isLinearLayout = root instanceof LinearLayout;
        if (isLinearLayout) {
            LinearLayout rootView = (LinearLayout) root;
            view = LayoutInflater.from(context).inflate(R.layout.top_toolbar, null);
            view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ConstantValue.TitleHeight));
            rootView.addView(view, 0);
            this.lltoolbar = (LinearLayout) view.findViewById(R.id.ll_toolbar);
            this.rltoolbarright = (RelativeLayout) view.findViewById(R.id.rl_toolbar_right);
            this.tvtoolbarright = (TextView) view.findViewById(R.id.tv_toolbar_right);
            this.ivtoolbarright = (ImageView) view.findViewById(R.id.iv_toolbar_right);
            this.rltoolbarcenter = (RelativeLayout) view.findViewById(R.id.rl_toolbar_center);
            this.tvtoolbarcenter = (TextView) view.findViewById(R.id.tv_toolbar_center);
            this.rltoolbarleft = (LinearLayout) view.findViewById(R.id.rl_toolbar_left);
            this.tvtoolbarleft = (TextView) view.findViewById(R.id.tv_toolbar_left);
            this.ivtoolbarleft = (ImageView) view.findViewById(R.id.iv_toolbar_left);
            setLeftOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    context.finish();
                }
            });
        }

    }

    public void setTitleBgRes(int resid) {
        if (!isLinearLayout) return;
        lltoolbar.setBackgroundResource(resid);
    }

    public void setTitleText(String text) {
        if (!isLinearLayout) return;
        tvtoolbarcenter.setVisibility(TextUtils.isEmpty(text) ? View.GONE
                : View.VISIBLE);
        tvtoolbarcenter.setText(text);
    }

    public void setLeftImage(int resId) {
        if (!isLinearLayout) return;
        ivtoolbarleft.setVisibility(resId > 0 ? View.VISIBLE : View.GONE);
        ivtoolbarleft.setImageResource(resId);
    }

    public void setLeftText(String text) {
        if (!isLinearLayout) return;
        tvtoolbarleft.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);
        tvtoolbarleft.setText(text);
    }

    public void setLeftOnClickListener(View.OnClickListener listener) {
        if (!isLinearLayout) return;
        if (ivtoolbarleft.getVisibility() == View.VISIBLE || tvtoolbarleft.getVisibility() == View.VISIBLE) {
            rltoolbarleft.setOnClickListener(listener);
        }
    }

    public void setRightImage(int resId) {
        if (!isLinearLayout) return;
        ivtoolbarright.setVisibility(resId > 0 ? View.VISIBLE : View.GONE);
        ivtoolbarright.setImageResource(resId);
    }

    public void setRightText(String text) {
        if (!isLinearLayout) return;
        tvtoolbarright.setVisibility(TextUtils.isEmpty(text) ? View.GONE
                : View.VISIBLE);
        tvtoolbarright.setText(text);
    }

    public void setRightOnClickListener(View.OnClickListener listener) {
        if (!isLinearLayout) return;
        if (ivtoolbarright.getVisibility() == View.VISIBLE || tvtoolbarright.getVisibility() == View.VISIBLE) {
            rltoolbarright.setOnClickListener(listener);
        }
    }

    public void setTitleOnClickListener(View.OnClickListener listener) {
        if (!isLinearLayout) return;
        if (tvtoolbarcenter.getVisibility() == View.VISIBLE) {
            rltoolbarcenter.setOnClickListener(listener);
        }
    }

    public void hideLeftSide() {
        if (!isLinearLayout) return;
        rltoolbarleft.setVisibility(View.INVISIBLE);
    }

    public void hideRightSide() {
        if (!isLinearLayout) return;
        rltoolbarright.setVisibility(View.INVISIBLE);
    }

    public void hideToolbar() {
        if (!isLinearLayout) return;
        lltoolbar.setVisibility(View.GONE);
    }

    public View build() {
        if (isLinearLayout)
            return view;
        return null;
    }
}
PreferencesUtil.java
package com.laundrylangpickcargo.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;

import com.laundrylangpickcargo.mai.BaseApplication;

import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Created by Sinaan on 2016/9/30.
 * SharedPreferences工具类
 */
public class PreferencesUtil {

    private static Context context = BaseApplication.getInstance();
    private final static String DEFAULT_STRING_VALUE = "";
    private final static boolean DEFAULT_BOOLEAN_VALUE = false;
    private final static float DEFAULT_FLOAT_VALUE = -1f;
    private final static int DEFAULT_INTEGER_VALUE = -1;
    private final static long DEFAULT_LONG_VALUE = -1l;
    private final static Set<String> DEFAULT_SET_VALUE = null;
    private static HashSet<String> shared_prefs = new HashSet<>();

    public static void put(@NonNull String SHPNAME,Map<String,Object> map){
        for (Map.Entry<String, ?> entry: map.entrySet()) {
            String k = entry.getKey();
            Object v = entry.getValue();
            put(SHPNAME,k,v);
        }
    }

    public static void put(@NonNull String SHPNAME,@NonNull String key,Object value){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        shared_prefs.add(SHPNAME);
        SharedPreferences.Editor edit = shp.edit();
        if(value instanceof String)
            edit.putString(key,(String)value);
        if(value instanceof Boolean)
            edit.putBoolean(key, (Boolean) value);
        if(value instanceof Float)
            edit.putFloat(key, (Float) value);
        if(value instanceof Long)
            edit.putLong(key, (Long) value);
        if(value instanceof Integer)
            edit.putInt(key, (Integer) value);
        if(value instanceof Set)
            edit.putStringSet(key, (Set<String>) value);
        edit.apply();
    }

    public static Map<String, ?> getAll(@NonNull String SHPNAME){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getAll();
    }

    public static String getString(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getString(key, DEFAULT_STRING_VALUE);
    }

    public static boolean getBoolean(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getBoolean(key, DEFAULT_BOOLEAN_VALUE);
    }

    public static float getFloat(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getFloat(key, DEFAULT_FLOAT_VALUE);
    }

    public static int getInt(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getInt(key, DEFAULT_INTEGER_VALUE);
    }

    public static long getLong(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getLong(key, DEFAULT_LONG_VALUE);
    }

    public static Set<String> getStringSet(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        return shp.getStringSet(key, DEFAULT_SET_VALUE);
    }

    public static void clearAll() {
        Iterator<String> iterator = shared_prefs.iterator();
        while(iterator.hasNext()){
            String SHPNAME = iterator.next();
            clear(SHPNAME);
        }

        File file = new File("/data/data/" + VersionManager.getPackageName(context) + "/shared_prefs");
        if (file != null && file.exists() && file.isDirectory()) {
            for (File item : file.listFiles()) {
                item.delete();
            }
            file.delete();
        }
    }

    public static void clear(@NonNull String SHPNAME){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        shp.edit().clear().apply();
    }

    public static void clear(@NonNull String SHPNAME,@NonNull String key){
        SharedPreferences shp = context.getSharedPreferences(SHPNAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = shp.edit();

        Map<String, ?> all = getAll(SHPNAME);
        for (Map.Entry<String, ?> entry: all.entrySet()) {
            String k = entry.getKey();
            Object v = entry.getValue();

            if(key.equals(k)){
                if(v instanceof String)
                    edit.putString(key,DEFAULT_STRING_VALUE);
                if(v instanceof Boolean)
                    edit.putBoolean(key,DEFAULT_BOOLEAN_VALUE);
                if(v instanceof Float)
                    edit.putFloat(key, DEFAULT_FLOAT_VALUE);
                if(v instanceof Long)
                    edit.putLong(key, DEFAULT_LONG_VALUE);
                if(v instanceof Integer)
                    edit.putInt(key, DEFAULT_INTEGER_VALUE);
                if(v instanceof Set)
                    edit.putStringSet(key, DEFAULT_SET_VALUE);
                edit.apply();
            }
        }

    }
}
TypefaceUtil.java
package com.laundrylangpickcargo.util;

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.lang.reflect.Field;

/*
 * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 字体设置工具类
 */
public class TypefaceUtil {
    /**
     * 为给定的字符串添加HTML红色标记,当使用Html.fromHtml()方式显示到TextView 的时候其将是红色的
     *
     * @param string 给定的字符串
     * @return
     */
    public static String addHtmlRedFlag(String string) {
        return "<font color=\"red\">" + string + "</font>";
    }

    /**
     * 将给定的字符串中所有给定的关键字标红
     *
     * @param sourceString 给定的字符串
     * @param keyword      给定的关键字
     * @return 返回的是带Html标签的字符串,在使用时要通过Html.fromHtml()转换为Spanned对象再传递给TextView对象
     */
    public static String keywordMadeRed(String sourceString, String keyword) {
        String result = "";
        if (sourceString != null && !"".equals(sourceString.trim())) {
            if (keyword != null && !"".equals(keyword.trim())) {
                result = sourceString.replaceAll(keyword, "<font color=\"red\">" + keyword + "</font>");
            } else {
                result = sourceString;
            }
        }
        return result;
    }

    /**
     * <p>Replace the font of specified view and it's children</p>
     * @param root The root view.
     * @param fontPath font file path relative to 'assets' directory.
     */
    public static void replaceFont(@NonNull View root, String fontPath) {
        if (root == null || TextUtils.isEmpty(fontPath)) {
            return;
        }


        if (root instanceof TextView) { // If view is TextView or it's subclass, replace it's font
            TextView textView = (TextView)root;
            int style = Typeface.NORMAL;
            if (textView.getTypeface() != null) {
                style = textView.getTypeface().getStyle();
            }
            textView.setTypeface(createTypeface(root.getContext(), fontPath), style);
        } else if (root instanceof ViewGroup) { // If view is ViewGroup, apply this method on it's child views
            ViewGroup viewGroup = (ViewGroup) root;
            for (int i = 0; i < viewGroup.getChildCount(); ++i) {
                replaceFont(viewGroup.getChildAt(i), fontPath);
            }
        }
    }

    /**
     * <p>Replace the font of specified view and it's children</p>
     * 通过递归批量替换某个View及其子View的字体改变Activity内部控件的字体(TextView,Button,EditText,CheckBox,RadioButton等)
     * @param context The view corresponding to the activity.
     * @param fontPath font file path relative to 'assets' directory.
     */
    public static void replaceFont(@NonNull Activity context, String fontPath) {
        replaceFont(getRootView(context),fontPath);
    }


    /*
     * Create a Typeface instance with your font file
     */
    public static Typeface createTypeface(Context context, String fontPath) {
        return Typeface.createFromAsset(context.getAssets(), fontPath);
    }

    /**
     * 从Activity 获取 rootView 根节点
     * @param context
     * @return 当前activity布局的根节点
     */
    public static View getRootView(Activity context)
    {
        return ((ViewGroup)context.findViewById(android.R.id.content)).getChildAt(0);
    }

    /**
     * 通过改变App的系统字体替换App内部所有控件的字体(TextView,Button,EditText,CheckBox,RadioButton等)
     * @param context
     * @param fontPath
     * 需要修改style样式为monospace:
     */
//    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
//    <!-- Customize your theme here. -->
//    <!-- Set system default typeface -->
//    <item name="android:typeface">monospace</item>
//    </style>
    public static void replaceSystemDefaultFont(@NonNull Context context, @NonNull String fontPath) {
        replaceTypefaceField("MONOSPACE", createTypeface(context, fontPath));
    }

    /**
     * <p>Replace field in class Typeface with reflection.</p>
     */
    private static void replaceTypefaceField(String fieldName, Object value) {
        try {
            Field defaultField = Typeface.class.getDeclaredField(fieldName);
            defaultField.setAccessible(true);
            defaultField.set(null, value);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`BaseActivity` 是 Android 开发中的一种设计模式,用于封装一些公共的 Activity 逻辑,以便在多个 Activity 中复用。 具体来说,`BaseActivity` 是一个抽象类,它继承自 Android 系统提供的 `Activity` 类。在 `BaseActivity` 中,开发者可以定义一些公共的方法、成员变量和生命周期回调方法,供子类继承和复用。 例如,假设我们在多个 Activity 中都需要显示一个 Loading 对话框,那么可以在 `BaseActivity` 中定义一个显示 Loading 对话框的方法: ```java public abstract class BaseActivity extends Activity { private ProgressDialog mProgressDialog; protected void showLoadingDialog() { if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(this); mProgressDialog.setMessage("Loading..."); mProgressDialog.setCanceledOnTouchOutside(false); } mProgressDialog.show(); } protected void hideLoadingDialog() { if (mProgressDialog != null) { mProgressDialog.dismiss(); } } } ``` 在子类中,只需要调用 `showLoadingDialog()` 和 `hideLoadingDialog()` 方法即可显示和隐藏 Loading 对话框: ```java public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); showLoadingDialog(); // do some time-consuming task hideLoadingDialog(); } } ``` 这个代码会在 `MainActivity` 中显示一个 Loading 对话框,并在执行一些耗时任务后隐藏对话框。这样,开发者就可以在多个 Activity 中复用显示和隐藏 Loading 对话框的逻辑了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值