探究ViewPager延迟加载

最近用户反映打开APP的时候非常卡顿。对ViewPager的延迟加载进行了探究。

对首页进行简单分析

  • 看一下代码片段
    private void addFragments() {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        for (Fragment f : mFragments) {
            ft.add(R.id.fl_content, f);
        }
        ft.commit();
    }

    private void showFragment(int index) {
        FragmentTransaction transaction = mManager.beginTransaction();
        for (int i = 0; i < mFragments.size(); i++) {
            if (i == index) {
                transaction.show(mFragments.get(i));
            } else {
                transaction.hide(mFragments.get(i));
            }
        }
        transaction.commit();
    }

初始的时候,将所有涉及到的Fragment都添加进来,根据用户点击的tab来显示相应的Fragment。

  • 通过log查看一下Fragment和Activity相应的生命周期

1.新启动MainActivity的时候:

四个Fragment都有创建。在Fragment onResume中加载网络数据,必然导致进入主页非常慢(AsyncTask默认是串行执行的)。
2.切换到任何一个Fragment,该Fragment的onResume都没有调用。尝试使用setUserVisibleHint,测试结果这种方法也行不通。
3.进入子页面返回后:
探究ViewPager延迟加载_第1张图片
这是正常的,Fragment和它所在的Activity有相似的生命周期。
可见单纯的在onResume中,刷新网络数据时行不通了。只能将更新网络数据的逻辑放在了MainActivity中了,这样一来,Activity和Fragment的耦合度太高了,这种方式的确不大好啊!!!

2.使用ViewPager+Fragment 懒加载

1.科普一下:FragmentPagerAdapter和FragmentStatePagerAdapter来自android.support.v4.app包用来构建ViewPager。
FragmentPagerAdapter更多的用于少量界面的ViewPager,比如Tab。划过的fragment会保存在内存中,尽管已经划过。 而FragmentStatePagerAdapter和ListView有点类似,会保存当前界面,以及下一个界面和上一个界面(如果有),最多保存3 个,其他会被销毁掉。所以,我们这里使用FragmentPagerAdapter,FragmentPagerAdapter默认仅仅加载当前页面和两侧页面到内存中其他都从内存中移除,我们这里设置mPager.setOffscreenPageLimit(3);保证一次将所有的Fragment都添加到内存中,当tab进行切换的时候,不会再有Fragment的创建。
2.初始情况:

可以看到C的延迟加载有调用
3.点击A:
这里写图片描述
这里延迟加载有调用哦!
4.进入子页面然后返回:

现在仅仅在Fragment的layzLoad中更新数据就好了。如果想要获取fragment从二级子页面返回的事件,使用startActivityForResult 来进行处理就好啦!

3.罗列一下相关代码

  • LazyFragment一个大神的成果,借用一下
package com.example.fragmentstatepageradapterdemo.fragment;
import android.support.v4.app.Fragment;  

/** * Author: msdx ([email protected]) * Time: 14-7-17 下午5:46 */  
public abstract class LazyFragment extends Fragment {  
    protected boolean isVisible;  
    /** * 在这里实现Fragment数据的缓加载. * @param isVisibleToUser */  
    @Override  
    public void setUserVisibleHint(boolean isVisibleToUser) {  
        super.setUserVisibleHint(isVisibleToUser);  
        if(getUserVisibleHint()) {  
            isVisible = true;  
            onVisible();  
        } else {  
            isVisible = false;  
            onInvisible();  
        }  
    }  

    protected void onVisible(){  
        lazyLoad();  
    }  

    protected abstract void lazyLoad();  

    protected void onInvisible(){}  
}  
  • AFragment添加了进入子页面的事件
package com.example.fragmentstatepageradapterdemo.fragment;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.fragmentstatepageradapterdemo.SecondActivity;
import com.example.fragmentstatepageradapterdemo.ViewPagerMainActivity;

public class AFragment extends LazyFragment {

     // 标志位,标志已经初始化完成。 
    private boolean isPrepared;  
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        TextView tv = new TextView(getActivity());
        //获取当前class名的方法
        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();
    //获取当前method名的方法
        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        tv.setText(clazz);
        tv.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                startActivity(new Intent(getActivity(), SecondActivity.class));
            }
        });
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);
          isPrepared = true;  
            lazyLoad();  
        return tv;
    }

    @Override
    public void onResume() {
        super.onResume();
        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();
        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);

    }

    @Override
    protected void lazyLoad() {
           if(!isPrepared || !isVisible) {  
                return;  
            } 
           String clazz = Thread.currentThread().getStackTrace()[2]
                    .getClassName();
            String method = Thread.currentThread().getStackTrace()[2]
                    .getMethodName();
            String msg = " " + clazz + " " + method;
            Log.d(ViewPagerMainActivity.TAG, msg);


            //填充各控件的数据 
    }
}

B/C/D和A相似。

  • SecondActivity主要是打印一下生命周期信息
package com.example.fragmentstatepageradapterdemo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();

        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        tv.setText(clazz);
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);
        setContentView(tv);
    }

    @Override
    protected void onResume() {
        super.onResume();

        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();

        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);

    }

    @Override
    protected void onPause() {
        super.onPause();

        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();

        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);

    }

}
  • 测试MainActivity的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#eeeeee" android:orientation="vertical" >
    <android.support.v4.view.ViewPager  android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="0px" android:layout_weight="1" >
    </android.support.v4.view.ViewPager>
    <View  android:id="@+id/line" android:layout_width="fill_parent" android:layout_height="1px" android:background="#cacaca" />
    <LinearLayout  android:id="@+id/ll_bottoms" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#f5f5f5" android:baselineAligned="false" android:orientation="horizontal" >
        <FrameLayout  android:id="@+id/fl_a" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" android:clickable="true" >

            <RadioButton  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:button="@drawable/ic_launcher" android:clickable="false" />
        </FrameLayout>
        <FrameLayout  android:id="@+id/fl_b" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" android:clickable="true" >
            <RadioButton  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:button="@drawable/ic_launcher" android:clickable="false" />
        </FrameLayout>
        <FrameLayout  android:id="@+id/fl_c" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" android:clickable="true" >
            <RadioButton  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:button="@drawable/ic_launcher" android:clickable="false" />
        </FrameLayout>
        <FrameLayout  android:id="@+id/fl_d" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" android:clickable="true" >
            <RadioButton  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:button="@drawable/ic_launcher" android:clickable="false" />
        </FrameLayout>
    </LinearLayout>
</LinearLayout>
  • 测试MainActivity
package com.example.fragmentstatepageradapterdemo;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

import com.example.fragmentstatepageradapterdemo.fragment.AFragment;
import com.example.fragmentstatepageradapterdemo.fragment.BFragment;
import com.example.fragmentstatepageradapterdemo.fragment.CFragment;
import com.example.fragmentstatepageradapterdemo.fragment.DFragment;

public class ViewPagerMainActivity extends FragmentActivity implements View.OnClickListener {
    public static final String TAG = ViewPagerMainActivity.class.getSimpleName();
    public static final int FRAG_A = 0;
    public static final int FRAG_B = 1;
    public static final int FRAG_C = 2;
    public static final int FRAG_D = 3;
    private List<Fragment> mFragments = new ArrayList<Fragment>();

    MyAdapter mAdapter;
    ViewPager mPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_main_viewpager);

        LinearLayout bottomLayout = (LinearLayout) findViewById(R.id.ll_bottoms);
        LinearLayout.LayoutParams bottomParams = (LayoutParams) bottomLayout
                .getLayoutParams();
        bottomParams.height = 98;
        findViewById(R.id.fl_a).setOnClickListener(this);
        findViewById(R.id.fl_b).setOnClickListener(this);
        findViewById(R.id.fl_c).setOnClickListener(this);
        findViewById(R.id.fl_d).setOnClickListener(this);
        mFragments = new ArrayList<Fragment>();
        mFragments.add(FRAG_A, new AFragment());
        mFragments.add(FRAG_B, new BFragment());
        mFragments.add(FRAG_C, new CFragment());
        mFragments.add(FRAG_D, new DFragment());
        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();

        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);

        mAdapter = new MyAdapter(getSupportFragmentManager());

        mPager = (ViewPager) findViewById(R.id.pager);
        mPager.setOffscreenPageLimit(3);
        mPager.setAdapter(mAdapter);
        mPager.setCurrentItem(2);

    }
    public class MyAdapter extends FragmentPagerAdapter{

        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int postion) {
            return mFragments.get(postion);
        }

        @Override
        public int getCount() {
            return mFragments==null? 0:mFragments.size();
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        String clazz = Thread.currentThread().getStackTrace()[2].getClassName();

        String method = Thread.currentThread().getStackTrace()[2]
                .getMethodName();
        String msg = " " + clazz + " " + method;
        Log.d(ViewPagerMainActivity.TAG, msg);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.fl_b: {
            // loginOrShow(FRAG_B);
            mPager.setCurrentItem(1);
            break;
        }

        case R.id.fl_c: {
            // loginOrShow(FRAG_C);
            mPager.setCurrentItem(2);
            break;
        }

        case R.id.fl_d: {
            mPager.setCurrentItem(3);
            // loginOrShow(FRAG_D);
            break;
        }

        default:
        case R.id.fl_a: {
            mPager.setCurrentItem(0);
            // loginOrShow(FRAG_A);
            break;
        }
        }
    }


}

你可能感兴趣的:(app优化)