Android 怎样提高页面的相应速度呢?

1.使用Fragment代替Activity来显示页面

我们都知道Activity的启动和销毁需要进行view的创建和销毁以及其他资源的创建与销毁(比如:BroadCaster, 数据库, 网络等), 这将花费一定的时间,这是导致页面启动显示慢的原因之一.如果使用Fragment来代替Activity来显示页面,避开Activity的创建和销毁,可以显著的提高用户体验,这也是现在绝大部分应用采用的做法.废话不多说,上代码:

首先我们要定义一个BaseActivity用来处理一些activity公共的操作,请看代码:

/**
 * @author kevin
 */
public abstract class BaseActivity extends AppCompatActivity {
    public Activity activity;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        doBeforeSetContentView();
        setContentView(getLayoutId());
        doAfterSetContentView();
        initPresenter();
        initView(savedInstanceState);
    }

    
    @SuppressLint("SourceLockedOrientationActivity")
    private void doBeforeSetContentView() {
        // 把activity放到application栈中管理
        AppManager.getAppManager().addActivity(this);
        // 设置全屏
        setFullScreen();
        // 设置竖屏
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    private void doAfterSetContentView() {
        //点击activity中除键盘任意其他的地方可收回键盘
        HideIMEUtil.wrap(this);
        activity = this;
    }

    /**
     * 获取布局文件
     *
     * @return 返回具体fragment对应的Id
     */
    protected abstract @LayoutRes
    int getLayoutId();

    //简单页面无需mvp就不用管此方法即可,完美兼容各种实际场景的变通
    public abstract void initPresenter();

    //初始化view
    public abstract void initView(@Nullable Bundle savedInstanceState);


    public void setFullScreen() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        AppManager.getAppManager().finishActivity(this);
    }
}

我们注意到上面的getLayoutId()方法,这个方法由个特定的activity来override, 比方我们来看看其中一个activity, ContainterActivity.



/**
 * @author kevin //只是一个容器activtiy,用来装载各种fragement
 */
public class ContainerActivity extends BaseActivity {
    ...

    @Override
    protected int getLayoutId() {
        return R.layout.activity_container;
    }

    @Override
    public void initPresenter() {

    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public void initView(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            mainFragment = (MainFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.MAIN_FRAGMENT);
            if (mainFragment == null) {
                createAndAddMainFragment();
            }
            lightFragment = (LightFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.LIGHT_FRAGMENT);
            if (lightFragment == null) {
                createAndAddLightFragment();
            }
            cameraFragment = (CameraFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.CAMERA_FRAGMENT);
            if (cameraFragment == null) {
                createAndAddCameraFragment();
            }
            deashingFragment = (DeashingFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.DEASHING_FRAGMENT);
            if (deashingFragment == null) {
                createAndAddDeashingFragment();
            }
            sortingFragment = (SortingFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.SORTING_FRAGMENT);
            if (sortingFragment == null) {
                createAndAddSortingFragment();
            }
            vibratorFragment = (VibratorFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.VIBRATOR_FRAGMENT);
            if (vibratorFragment == null) {
                createAndAddVibratorFragment();
            }
            downloadFragment = (DownloadFragment) getSupportFragmentManager().getFragment(savedInstanceState, Constants.DOWNLOAD_FRAGMENT);
            if (downloadFragment == null) {
                createAndAddDownloadFragment();
            }
        } else {
            createAndAddMainFragment();
        }
        showOrHideFragment(Constants.MAIN_FRAGMENT);
        ...
    }





    /**
     * 显示和隐藏fragment的状态机
     */
    public void showOrHideFragment(String fragmentTab) {


        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

        if (mainFragment != null) {
            if (fragmentTab.equals(Constants.MAIN_FRAGMENT)) {
                fragmentTransaction.show(mainFragment);
            } else {
                fragmentTransaction.hide(mainFragment);
            }
        }
        if (lightFragment != null) {
            if (fragmentTab.equals(Constants.LIGHT_FRAGMENT)) {
                fragmentTransaction.show(lightFragment);
            } else {
                fragmentTransaction.hide(lightFragment);
            }
        }

        if (cameraFragment != null) {
            if (fragmentTab.equals(Constants.CAMERA_FRAGMENT)) {
                fragmentTransaction.show(cameraFragment);
            } else {
                fragmentTransaction.hide(cameraFragment);
            }
        }

        if (deashingFragment != null) {
            if (fragmentTab.equals(Constants.DEASHING_FRAGMENT)) {
                fragmentTransaction.show(deashingFragment);
            } else {
                fragmentTransaction.hide(deashingFragment);
            }
        }

        if (sortingFragment != null) {
            if (fragmentTab.equals(Constants.SORTING_FRAGMENT)) {
                fragmentTransaction.show(sortingFragment);
            } else {
                fragmentTransaction.hide(sortingFragment);
            }
        }
        if (vibratorFragment != null) {
            if (fragmentTab.equals(Constants.VIBRATOR_FRAGMENT)) {
                fragmentTransaction.show(vibratorFragment);
            } else {
                fragmentTransaction.hide(vibratorFragment);
            }
        }
        if (downloadFragment != null) {
            if (fragmentTab.equals(Constants.DOWNLOAD_FRAGMENT)) {
                fragmentTransaction.show(downloadFragment);
            } else {
                fragmentTransaction.hide(downloadFragment);
            }
        }

        fragmentTransaction.commit();

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);

        if (intent != null) {
            String tag;
            tag = intent.getStringExtra(Constants.BUNDLE_KEY_WHERE_TO_GO);
            LogUtil.d(TAG, " tag : " + tag);
            if (null != tag && tag.length() > 1) {
                switch (tag) {
                    case Constants.CAMERA_FRAGMENT:
                        createAndAddCameraFragment();
                        currentTab = Constants.CAMERA_FRAGMENT;
                        break;
                    case Constants.LIGHT_FRAGMENT:
                        createAndAddLightFragment();
                        currentTab = Constants.LIGHT_FRAGMENT;
                        break;
                    case Constants.DEASHING_FRAGMENT:
                        createAndAddDeashingFragment();
                        currentTab = Constants.DEASHING_FRAGMENT;
                        break;
                    case Constants.DOWNLOAD_FRAGMENT:
                        createAndAddDownloadFragment();
                        currentTab = Constants.DOWNLOAD_FRAGMENT;
                        break;
                    case Constants.SORTING_FRAGMENT:
                        createAndAddSortingFragment();
                        currentTab = Constants.SORTING_FRAGMENT;
                        break;
                    case Constants.VIBRATOR_FRAGMENT:
                        createAndAddVibratorFragment();
                        currentTab = Constants.VIBRATOR_FRAGMENT;
                        break;
                    default:
                        createAndAddMainFragment();
                        currentTab = Constants.MAIN_FRAGMENT;
                        break;
                }
                showOrHideFragment(currentTab);
            }
        }
    }

    private void createAndAddMainFragment() {
        if (mainFragment == null) {
            mainFragment = MainFragment.newInstance();
        }
        if (!mainFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, mainFragment, MainFragment.class.getName()).commit();
        }

    }

    private void createAndAddCameraFragment() {
        if (cameraFragment == null) {
            cameraFragment = CameraFragment.newInstance();
        }
        if (!cameraFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, cameraFragment, CameraFragment.class.getName()).commit();
        }
    }

    private void createAndAddLightFragment() {
        if (lightFragment == null) {
            lightFragment = LightFragment.newInstance();
        }
        if (!lightFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, lightFragment, LightFragment.class.getName()).commit();
        }
    }

    private void createAndAddDeashingFragment() {
        if (deashingFragment == null) {
            deashingFragment = DeashingFragment.newInstance();
        }
        if (!deashingFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, deashingFragment, DeashingFragment.class.getName()).commit();
        }
    }

    private void createAndAddDownloadFragment() {
        if (downloadFragment == null) {
            downloadFragment = DownloadFragment.newInstance();
        }
        if (!downloadFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, downloadFragment, DownloadFragment.class.getName()).commit();
        }
    }

    private void createAndAddSortingFragment() {
        if (sortingFragment == null) {
            sortingFragment = SortingFragment.newInstance();
        }
        if (!sortingFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, sortingFragment, SortingFragment.class.getName()).commit();
        }
    }

    private void createAndAddVibratorFragment() {
        if (vibratorFragment == null) {
            vibratorFragment = VibratorFragment.newInstance();
        }
        if (!vibratorFragment.isAdded()) {
            getSupportFragmentManager().beginTransaction().add(R.id.frame_content, vibratorFragment, VibratorFragment.class.getName()).commit();
        }
    }


    @Override
    public void onBackPressed() {
        //如果是主页面就退出
        if (currentTab.equals(Constants.MAIN_FRAGMENT)) {
            DialogUtil.createAlertDialog(this, "", StringUtil.getString(R.string.really_want_exit));

        } else {
            switch (currentTab) {
                case Constants.CAMERA_FRAGMENT:
                    if (cameraFragment != null) {
                        if (cameraFragment.onBackPressed()) {
                            break;
                        } else {
                            return;
                        }
                    }
                    break;
                case Constants.LIGHT_FRAGMENT:
                    if (lightFragment != null) {
                        if (lightFragment.onBackPressed()) {
                            break;
                        } else {
                            return;
                        }
                    }
                    break;
                case Constants.DEASHING_FRAGMENT:
                    if (deashingFragment != null) {
                        if (deashingFragment.onBackPressed()) {
                            break;
                        }else {
                            return;
                        }
                    }
                    break;
                case Constants.DOWNLOAD_FRAGMENT:
                    if (downloadFragment != null) {
                        if (downloadFragment.onBackPressed()) {
                            break;
                        }else {
                            return;
                        }
                    }
                    break;
                case Constants.SORTING_FRAGMENT:
                    if (sortingFragment != null) {
                        if (sortingFragment.onBackPressed()) {
                            break;
                        }else {
                            return;
                        }
                    }
                    break;
                case Constants.VIBRATOR_FRAGMENT:
                    if (vibratorFragment != null) {
                        if (vibratorFragment.onBackPressed()) {
                            break;
                        }else {
                            return;
                        }
                    }
                    break;
                default:
                    break;
            }
            currentTab = Constants.MAIN_FRAGMENT;
            showOrHideFragment(currentTab);
        }
    }
   
}

 

为什么我用Contanter来命名,是因为这个activity像个容器一样可以装着 MainFragment, LightFragment,CameraFragment等一个Fragment,然后控制他们的切换,那么ContainerActivity的布局文件中又有什么呢?我们来看一下:

点进去,

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frame_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

咦,就是一个简单的FrameLayout,那么界面的布局在哪儿写呢? 别慌各位看客们,估计聪明的你肯定想到写到Fragment每个对应的布局文件中去了, Bingo, 对的就是在那里,我们一起去看看吧. 别慌先看看代码的组织结构,这样方便理解.

Java代码结构如下:

Layout文件结构如下:

那么fragment_main的具体代码如下:

​
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/turquoise"
    android:orientation="vertical"
    tools:context=".fragment.sub.MainFragment">
    <Spinner
        android:id="@+id/language_choice"
        style="@style/language_choice_style"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Spinner
        android:id="@+id/machine_type"
        style="@style/machine_type_style"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/language_choice" />

    <TextView
        android:id="@+id/version_number"
        style="@style/main_textview_style"
        android:text="@string/version_number"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <com.xxx.drag.DragFlowLayout
        android:id="@+id/drag_flowLayout"
        android:layout_width="800dp"
        android:layout_height="500dp"
        android:layout_marginStart="208dp"
        android:layout_marginLeft="208dp"
        android:layout_marginTop="192dp"
        app:flowLayout_horizontal_space="50dp"
        app:flowLayout_vertical_space="50dp"
        app:flowLayout_maxLine="2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="RtlHardcoded" />

    <com.xxx.colorsorter.ui.button.FlowingDrawableButton
        android:id="@+id/company_copyright"
        style="@style/company_copyright_style"
        app:drawableLeft="@drawable/logo"
        app:drawableHeight="46dp"
        app:drawableWidth="150dp"
        android:text="@string/company_copyright"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

​

那么这布局怎么加载的呢?那么来看看BaseFragment.如下:

/**
 * @author kevin
 */
public abstract class BaseFragment extends Fragment {
    private static final String TAG = BaseFragment.class.getSimpleName();
    protected View containerView;
    protected boolean hasViewCreated = false;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      

    }

  

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        containerView = inflater.inflate(getLayoutId(), container, false);
        return containerView;
    }

    /**
     * 获取布局文件
     *
     * @return the id of concrete fragment
     */
    protected abstract @LayoutRes
    int getLayoutId();


  

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        //不在最前端界面显示
        if (hidden) {
            onHide();
        } else if (hasViewCreated) {
            onShow();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /**
     * 当这个fragment显示时调用
     */
    public abstract void onShow();


    /**
     * 获取数据模型
     */
    protected abstract void getModel();

    /**
     * 当这个fragment隐藏时调用
     */
    protected abstract void onHide();

    /**
     * 当用户按返回键时调用,返回true时,可以退出当前的fragment,否则的话,还是当前fragment
     */
    public boolean onBackPressed() {
    }

    /**
     * 保存
     */
    public abstract void save();

    /**
     * 刷新
     */
    public void refreshUi() {

    }

    /**
     * 通过Class跳转界面
     **/
    public void startActivity(Class<?> cls) {
        startActivity(cls, null);
    }

    /**
     * 通过Class跳转界面
     **/
    public void startActivityForResult(Class<?> cls, int requestCode) {
        startActivityForResult(cls, null, requestCode);
    }

    /**
     * 含有Bundle通过Class跳转界面
     **/
    public void startActivityForResult(Class<?> cls, Bundle bundle,
                                       int requestCode) {
        Intent intent = new Intent();
        intent.setClass(getActivity(), cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

   
}

BaseFragment就是对各个fragment要用的公共方法的一个抽取. 所以,MainFragment的界面的具体加载自然在MainFragment.java中.我们来看看吧:


/**
 * @author kevin
 */
public class MainFragment extends BaseFragment {
   ...

    /**
     * onCreateView has already called in super class
     */
    @Override
    protected int getLayoutId() {
        return R.layout.fragment_main;
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ...
        initDrawFlowLayout(view);
        ...
    }

    private void initDrawFlowLayout(@NonNull View view) {
        ...
        dragFlowLayout.setOnItemClickListener(new DragFlowLayout.OnItemClickListener() {
            @Override
            public boolean performClick(DragFlowLayout dragFlowLayout, View child, MotionEvent event, int dragState) {
               
                DrawableButton drawableButton = child.findViewById(R.id.drawable_button);
                switch (event.getAction()) {
                    ...
                    case MotionEvent.ACTION_UP:
                        int tag = (int) drawableButton.getTag();
                        switch (tag) {
                            case R.string.sorting:
                                sortingOnClick();
                                break;
                            case R.string.camera_setting:
                                cameraSettingOnClick();
                                break;
                            case R.string.deashing_setting:
                                deashingSettingOnClick();
                                break;
                            case R.string.vibrator_setting:
                                vibratorSettingOnClick();
                                break;
                            case R.string.light_setting:
                                lightSettingOnClick();
                                break;
                            case R.string.download_setting:
                                downloadSettingOnClick();
                                break;
                            default:
                                break;
                        }
                        break;
                }
                return true;
            }
        });
       ...
    }


    @Override
    public void onShow() {
        ...
    }

    @Override
    protected void onHide() {
        ...
    }

    @Override
    protected void getModel() {
        ...
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    ...
    }

    @Override
    public boolean onBackPressed() {
        save();
        return super.onBackPressed();
    }

    @Override
    public void save() {
        ...
    }

   

    private void lightSettingOnClick() {
        startActivitySingleton(Constants.LIGHT_FRAGMENT);
    }

    private void deashingSettingOnClick() {
        startActivitySingleton(Constants.DEASHING_FRAGMENT);
    }

    private void cameraSettingOnClick() {
        startActivitySingleton(Constants.CAMERA_FRAGMENT);
    }

    private void downloadSettingOnClick() {
        startActivitySingleton(Constants.DOWNLOAD_FRAGMENT);
    }

    private void vibratorSettingOnClick() {
        startActivitySingleton(Constants.VIBRATOR_FRAGMENT);
    }

    private void sortingOnClick() {
        startActivitySingleton(Constants.SORTING_FRAGMENT);
    }

}

还有一个问题,fragment是如何切换的呢?看上面 initDrawFlowLayout方法,一个switch,相信不用我废话,你就明白了吧.

2. 使用懒加载的方式

就是用户访问到的页面才创建和加载,比如上面的fragment,一开始用户进入主界面,就创建和加载主界面,其他的fragment都不创建和加载,如  在initView 中 createAndAddMainFragment. 数据的加载使用异步加载的方式,比较好些. 有些界面的view可以使用viewStub来占坑.

3.使用ConstraintLayout来减少布局的深度

我们知道以前,布局喜欢用LinearLayout不断的嵌套,这样导致xml的dom树很深,而xml的解析,一般会用到递归算法,这样严重影响性能.除了使用ConstraintLayout外,很多情况下使用<merge></merge>来代替LinearLayout来减少布局深度.比如如下:

<?xml version="1.0" encoding="utf-8"?>

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".fragment.sub.CameraFragment">

    <com.xxx.colorsorter.ui.scroll.ObservableScrollView
        android:id="@+id/camera_image_scrollview"
        android:layout_width="1280px"
        android:layout_height="256px"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_width="1280px"
        tools:layout_height="256px"
        tools:ignore="PxUsage">

        <ImageView
            android:id="@+id/camera_image"
            android:layout_width="2048px"
            android:layout_height="256px"
            android:adjustViewBounds="true"
            android:contentDescription="@string/image_from_camera"
            tools:ignore="PxUsage"
            tools:layout_height="200dp"
            tools:layout_width="match_parent"
            tools:scaleType="fitXY" />
    </com.xxx.colorsorter.ui.scroll.ObservableScrollView>


    <RelativeLayout
        android:id="@+id/slide_wrapper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@id/camera_image_scrollview"
        app:layout_constraintRight_toRightOf="@id/camera_image_scrollview"
        app:layout_constraintTop_toBottomOf="@id/camera_image_scrollview">


        <ImageView
            android:id="@+id/slide_ind"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:background="@drawable/bg_anim_up_arrow"
            android:contentDescription="@string/slide_indicator"
            android:scaleType="fitXY"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/color_ind"
            style="@style/camera_textview_style2"
            android:layout_marginEnd="150dp" />

        <TextView
            android:id="@+id/hsi_ind"
            style="@style/camera_textview_style2"
            android:layout_marginEnd="5dp" />
    </RelativeLayout>

</merge>

写完了,希望各位看客补充.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值