参考链接
viewpager+fragment的懒加载实现微信点击和滑动切换功能(切换效果)
Android 解决多个Fragment切换时不断实例化
背景:在用viewpager时,来切换fragment,将fragment放到一个list里,但是,加载时,不想一下子,都加载进去,那就用懒汉式加载;
一个不错的例子,源码下载
源码下载
1.首先弄一个lazyfragment,其他继承它
package com.automic.app.shengliqu.bustationbase.view;
import android.support.v4.app.Fragment;
/**
* 懒加载 fragment
*/
public abstract class LazyFragment extends Fragment {
//用于标记视图是否初始化
protected boolean isVisible;
//在onCreate方法之前调用,用来判断Fragment的UI是否是可见的
@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(){}
}
2.业务逻辑简单的fragment
package com.slide.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.socks.library.KLog;
import butterknife.ButterKnife;
/**
* @author null
* created at 2017/6/20 13:41
* description:LazyFragment使用懒加载方法,避免切换fragment的时候造成其它fragment onstart方法运行,lazyLoad方法代替onstart方法
*/
public class OneFragment extends LazyFragment {
// 标志fragment是否初始化完成
private boolean isPrepared;
private View view;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
if(view == null){
view = inflater.inflate(R.layout.fragment_one , container , false);
ButterKnife.inject(this, view);
KLog.e("TAG" , "oneFragment--onCreateView");
isPrepared = true;
lazyLoad();
}
return view;
}
@Override
protected void lazyLoad() {
if(!isPrepared || !isVisible) {
return;
}
KLog.e("TAG" , "oneFragment--lazyLoad");
}
}
写的几个fragment都要继承lazyfragment,然后按照常规写法;
3.复杂业务逻辑的fragment
package com.automic.app.shengliqu.busoilmoisture.view;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.automic.app.shengliqu.R;
import com.automic.app.shengliqu.baseparts.Constant;
import com.automic.app.shengliqu.busoilmoisture.adapter.HistoryDataAdapter;
import com.automic.app.shengliqu.busoilmoisture.bean.HistoryData;
import com.automic.app.shengliqu.busoilmoisture.bean.OneSmBaseData;
import com.automic.app.shengliqu.bustationbase.bean.MessageWatched;
import com.automic.app.shengliqu.bustationbase.view.LazyFragment;
import com.automic.app.shengliqu.bustationrain.adapter.SpinnerAdapter;
import com.automic.app.shengliqu.bustationrain.view.RainfallActivity;
import com.automic.app.shengliqu.utils.DateUtils;
import com.automic.app.shengliqu.utils.GsonUtils;
import com.automic.app.shengliqu.utils.HelloChartUtils;
import com.automic.app.shengliqu.utils.LogUtils;
import com.automic.app.shengliqu.utils.ToastUtils;
import com.bigkoo.pickerview.TimePickerView;
import com.bigkoo.pickerview.listener.CustomListener;
import com.google.gson.reflect.TypeToken;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.view.LineChartView;
import static com.automic.app.shengliqu.utils.DateUtils.makeTimePvBuilder;
/**
* 历史墒情
*/
public class SoilmoistureHistoryFragment extends LazyFragment implements Observer {
private View rootView;
private ListView mLvNews = null;
private LinearLayout lltitle;
private LineChartView chartHistory;
private Typeface mTf;
private RadioButton rbChart;
private RadioButton rbList;
private RequestQueue queue;
private List<List<PointValue>> m_listPointValuesList = new ArrayList<>();
private List<String> line1PointValueList = new ArrayList<>();
private List<String> line2PointValueList = new ArrayList<>();
private List<String> line3PointValueList = new ArrayList<>();
private List<String> line4PointValueList = new ArrayList<>();
private List<String> line5PointValueList = new ArrayList<>();
private List<String> line6PointValueList = new ArrayList<>();
private List<String> line7PointValueList = new ArrayList<>();
private List<AxisValue> m_axisXValue = new ArrayList<AxisValue>();//动态获取X轴坐标信息
final String arrDate[] = new String[]{"逐日墒情", "逐月墒情", "逐年墒情"};
final String arrType[] = new String[]{"土壤含水量(%)", "土壤盐分(ms/cm)", "土壤温度(℃)"};
private String mearsureDir = "20cm-40cm-60cm-80cm-100cm-120cm-150cm";//测量指标"20cm-40cm-60cm-80cm-100cm-120cm-150cm";
private boolean flag = false;//判断是不是还在加载中,如果还在加载中的话,就不能进行应用的切换
private Spinner spnDate;
private String type = "d";
private String typeMonitIndex = "wc";//T:土壤温度;EC土壤盐分;WC土壤含水量。
private Spinner spnType;
private List<HistoryData> m_smHistoryList;
private HistoryDataAdapter historyDataAdapter;
private TimePickerView pvTimeYear;
private TimePickerView pvTimeYearMonth;
private TimePickerView pvTimeEndYear;
private TimePickerView pvTimeStartYear;
private TextView tvwMonitorIndex;
private boolean isPrepared;//标志fragment是否初始化完成
public SoilmoistureHistoryFragment() {
watched = new MessageWatched();
watched.addObserver(this);
}
public static SoilmoistureHistoryFragment newInstance() {
SoilmoistureHistoryFragment chatFrg = new SoilmoistureHistoryFragment();
return chatFrg;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(R.layout.fragment_soilmoisture_history, container, false);
isPrepared = true;
setUpViews();
lazyLoad();
}
return rootView;
}
private void setUpViews() {
queue = Volley.newRequestQueue(getActivity());
initDatePicker();
//日期选择
spnDate = (Spinner) rootView.findViewById(R.id.time_select);
SpinnerAdapter spnDateAdapter = new SpinnerAdapter(getActivity(), arrDate);
spnDate.setAdapter(spnDateAdapter);
//监测指标类型
spnType = (Spinner) rootView.findViewById(R.id.type_select);
SpinnerAdapter spnTypeAdapter = new SpinnerAdapter(getActivity(), arrType);
spnType.setAdapter(spnTypeAdapter);
// 固定列表
mLvNews = (ListView) rootView.findViewById(R.id.lv_history);
mLvNews.setVisibility(View.VISIBLE);
//过程线
chartHistory = (LineChartView) rootView.findViewById(R.id.lineChart_history);
chartHistory.setVisibility(View.INVISIBLE);
//切换
rbChart = (RadioButton) rootView.findViewById(R.id.radio_chart);
rbList = (RadioButton) rootView.findViewById(R.id.radio_list);
lltitle = (LinearLayout) rootView.findViewById(R.id.lltitle_lv_chart);
tvwMonitorIndex = (TextView) lltitle.findViewById(R.id.tvw_index_monitor);
rbList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RadioButton rb_list = (RadioButton) v;
if (rb_list.isChecked()) {
chartHistory.setVisibility(View.GONE);
mLvNews.setVisibility(View.VISIBLE);
}
}
});
rbChart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RadioButton rb_chart = (RadioButton) v;
if (rb_chart.isChecked()) {
chartHistory.setVisibility(View.VISIBLE);
mLvNews.setVisibility(View.GONE);
}
}
});
}
/**
* 初始化监测指标选择
*/
private void initMonitorIndexSelect() {
spnType.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
typeMonitIndex = "wc";
} else if (position == 1) {
typeMonitIndex = "ec";
} else if (position == 2) {
typeMonitIndex = "t";
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
* 日期选择类型
*/
private void initDateSelect() {
spnDate.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int position, long arg3) {
if (position == 0) {
type = "d";
// 日
getData("d", "default");
// 用户还可以选择到年月即可,比如选择2014-3,则显示2014-3月31天的每天的累计降雨量数据,没有降雨量显示为0mm。
SoilMoistureActivity.tag = "single_month";
} else if (position == 1) {
type = "m";
// 月
getData("m", "default");
// 用户还可以选择到年即可,比如选择2014年,就显示2014年的12个月的累计降雨量月数据,没有降雨量显示为0mm。
SoilMoistureActivity.tag = "single_year";
} else if (position == 2) {
type = "y";
// 年
getData("y", "default");
// 用户还可以选择某年到某年,显示某年到某年的每年的降雨量累计值,根据显示的最大量控制选择的年间距。
SoilMoistureActivity.tag = "year";
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
/**
* 获取到历史信息转换为图表
*/
private void smHistoryResult2LineChart() {
//网络获取的数据
m_listPointValuesList.clear();//line集合清除
line1PointValueList.clear();
line2PointValueList.clear();
line3PointValueList.clear();
line4PointValueList.clear();
line5PointValueList.clear();
line6PointValueList.clear();
line7PointValueList.clear();
List<String> xList = new ArrayList<>();
String xcmData[] = mearsureDir.split("-");
//记住倒序
//获得x轴数据 不同统计方式,不同显示
int numPoint = m_smHistoryList.size();
for (int i = numPoint - 1; i >= 0; i--) {
//y cross loop
List<OneSmBaseData> mSmHisList = m_smHistoryList.get(i).getDataDetail();
makePvListBySmDirec(xcmData, mSmHisList);
//获取x轴坐标
//x cross loop
//???这里时间未优化
String time = m_smHistoryList.get(i).getDataTime();
xList.add(time);
}
m_axisXValue = HelloChartUtils.generateAxisXLables(xList);
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line1PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line2PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line3PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line4PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line5PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line6PointValueList));
m_listPointValuesList.add(HelloChartUtils.generatePointValue(line7PointValueList));
HelloChartUtils.generateLineChart(chartHistory, m_listPointValuesList, m_axisXValue);
chartHistory.setVisibility(View.INVISIBLE);
}
/**
* 装填7个墒情监测深度list数据
*
* @param xcmData
* @param mSmList
*/
private void makePvListBySmDirec(String[] xcmData, List<OneSmBaseData> mSmList) {
for (OneSmBaseData sm : mSmList) {
if (sm.getXcm().equals(xcmData[0])) {
line1PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
LogUtils.e("sjt", "数据为" + xcmData[0] + "数据为===" + sm.getDataV());
}
if (sm.getXcm().equals(xcmData[1])) {
line2PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
LogUtils.e("sjt", "数据为" + xcmData[1] + "数据为===" + sm.getDataV());
}
if (sm.getXcm().equals(xcmData[2])) {
LogUtils.e("sjt", "数据为" + xcmData[2] + "数据为===" + sm.getDataV());
line3PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
}
if (sm.getXcm().equals(xcmData[3])) {
LogUtils.e("sjt", "数据为" + xcmData[3] + "数据为===" + sm.getDataV());
line4PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
}
if (sm.getXcm().equals(xcmData[4])) {
LogUtils.e("sjt", "数据为" + xcmData[4] + "数据为===" + sm.getDataV());
line5PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
}
if (sm.getXcm().equals(xcmData[5])) {
LogUtils.e("sjt", "数据为" + xcmData[5] + "数据为===" + sm.getDataV());
line6PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
}
if (sm.getXcm().equals(xcmData[6])) {
LogUtils.e("sjt", "数据为" + xcmData[6] + "数据为===" + sm.getDataV());
line7PointValueList.add(sm.getDataV() != null ? sm.getDataV() : "0.00");
}
}
}
/**
* 网络请求某时某类型数据
*
* @param type
* @param time
*/
private void getData(String type, String time) {
ToastUtils.show(getActivity(), "历史时间" + time + "监测类型" + typeMonitIndex);
dealDataSuccessResult(result);
String url = "http://" + Constant.BASEIP + "/servlet/station/get.do?cmd=getRainHistory&timeType="
+ type + "&time=" + time + "&stcd=" + RainfallActivity.stcd + typeMonitIndex;
// Request a string response from the provided URL.
url = url.trim();
//System.out.println("历史墒情URL:"+url);
StringRequest stringRequest = new StringRequest(Request.Method.GET,
url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject json;
try {
json = new JSONObject(response);
String content = json.getString("result");
//System.out.println(content);
m_smHistoryList = GsonUtils.json2List(content,
new TypeToken<List<HistoryData>>() {
});
if (m_smHistoryList != null) {
// 填充列表
historyDataAdapter = new HistoryDataAdapter(getActivity(), m_smHistoryList);
mLvNews.setAdapter(historyDataAdapter);
if (m_smHistoryList.size() != 0) {
smHistoryResult2LineChart();
}
} else {
ToastUtils.show(getActivity(), "查询不到数据");
}
} catch (Exception ex) {
LogUtils.e("sjt", "异常" + ex);
//System.out.println("err---->" + ex);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
ToastUtils.show(getActivity(), "服务器开小差了!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
private void dealDataSuccessResult(String result) {
JSONObject json;
try {
json = new JSONObject(result);
String content = json.getString("result");
//System.out.println(content);
m_smHistoryList = GsonUtils.json2List(content,
new TypeToken<List<HistoryData>>() {
});
if (m_smHistoryList != null) {
// 填充列表
historyDataAdapter = new HistoryDataAdapter(getActivity(), m_smHistoryList);
mLvNews.setAdapter(historyDataAdapter);
historyDataAdapter.notifyDataSetChanged();
if (m_smHistoryList.size() != 0) {
smHistoryResult2LineChart();
}
}
} catch (Exception ex) {
LogUtils.e("sjt", "异常" + ex);
//System.out.println("err---->" + ex);
}
}
// 消息观察者
public static MessageWatched watched;
@Override
public void update(Observable os, Object o) {
String message = ((MessageWatched) os).getData();
if (message.equals("OPEN_DIALOG_HISTORY")) {
if (type.equals("d")) {
pvTimeYearMonth.show(tvwMonitorIndex);
getData("d", SoilMoistureActivity.startTime);
} else if (type.equals("m")) {
pvTimeYear.show(tvwMonitorIndex);
getData("m", SoilMoistureActivity.startTime);
} else if (type.equals("y")) {
pvTimeStartYear.show(tvwMonitorIndex);
getData("y", SoilMoistureActivity.startTime);
}
}
}
private void initDatePicker() {
//控制时间范围(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释)
//因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
Calendar selectedDate = Calendar.getInstance();
//时间选择器-起始年与终止年选择
initStartYearAndEndYear(getActivity(), selectedDate, tvwMonitorIndex, "选择起始年", "选择终止年");
//时间选择器-年月选择(逐日)
pvTimeYearMonth = makeTimePvBuilder(getActivity(), new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
// 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
String dataString = DateUtils.getTimeYearMonthFormat(date);
//((TextView) v).setText("时间:"+dataString);
//String dataCache= dataString.replace("年","-");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
// getSoilMoistureRtAndHisReport(TYPE_HISTORY, "d", stcd, format.format(date));
//getSoilMoistureRtAndHisReport(TYPE_HISTORY, "d", stcd, dataCache.substring(0,dataCache.length()-1));
}
}).setType(new boolean[]{true, true, false, false, false, false})//年月日时分秒 的显示与否,不设置则默认全部显示
.setLabel("年", "月", "", "", "", "")
.build();
//时间选择器-年选择(逐月)
pvTimeYear = makeTimePvBuilder(getActivity(), new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
// 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
String dataString = DateUtils.getTimeYearFormat(date);
//((TextView) v).setText("时间:"+dataString);
//String dataCache= dataString.replace("年","-");
SimpleDateFormat format = new SimpleDateFormat("yyyy");
// getSoilMoistureRtAndHisReport(TYPE_HISTORY, "d", stcd, format.format(date));
//getSoilMoistureRtAndHisReport(TYPE_HISTORY, "d", stcd, dataCache.substring(0,dataCache.length()-1));
}
}).setType(new boolean[]{true, false, false, false, false, false})//年月日时分秒 的显示与否,不设置则默认全部显示
.setLabel("年", "", "", "", "", "")
.build();
}
int numEndYear;
int numStartYear;
private void initStartYearAndEndYear(final Context context, Calendar selectedDate, final TextView m_yearSelectTv, String startYLable, final String endYLable) {
pvTimeEndYear = makeTimePvBuilder(context, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
SimpleDateFormat format = new SimpleDateFormat("yyyy");
numEndYear = Integer.parseInt(format.format(date));
}
}).setType(new boolean[]{true, false, false, false, false, false})//年月日时分秒 的显示与否,不设置则默认全部显示
.setLabel("年", "", "", "", "", "")
.setTitleText(endYLable)
.setLayoutRes(R.layout.pickerview_time, new CustomListener() {
@Override
public void customLayout(View v) {
Button btSubmit = (Button) v.findViewById(R.id.btnSubmit);
Button btCancel = (Button) v.findViewById(R.id.btnCancel);
final TextView textView = (TextView) v.findViewById(R.id.tvTitle);
textView.setText(endYLable);
btSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvTimeEndYear.returnData();
if (numEndYear <= numStartYear) {
ToastUtils.show(context, "终止年小于起始年,请重新选择!");
if (!pvTimeEndYear.isShowing()) {
pvTimeEndYear.show(m_yearSelectTv);
}
} else {
//m_yearSelectTv.setText("" + numStartYear + "年-" + numEndYear + "年");
//获取数据
//getData();
pvTimeEndYear.dismiss();
}
}
});
btCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pvTimeEndYear.dismiss();
}
});
}
})
.build();
pvTimeStartYear = makeTimePvBuilder(context, new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
SimpleDateFormat format = new SimpleDateFormat("yyyy");
numStartYear = Integer.parseInt(format.format(date));
pvTimeEndYear.show(m_yearSelectTv);
}
}).setType(new boolean[]{true, false, false, false, false, false})//年月日时分秒 的显示与否,不设置则默认全部显示
.setLabel("年", "", "", "", "", "")
.setTitleText(startYLable)
.build();
}
private String result = "{\n" +
"result:[{\n" +
"dataDetail:[\n" +
"{xcm: \"20cm\",dataV: 10.00},\n" +
"{xcm: \"40cm\",dataV: 11.00},\n" +
"{xcm: \"60cm\",dataV: 12.00},\n" +
"{xcm: \"80cm\",dataV: 13.00},\n" +
"{xcm: \"100cm\",dataV: 16.00},\n" +
"{xcm: \"120cm\",dataV: 14.00},\n" +
"{xcm: \"150cm\",dataV: 15.00}],\n" +
"dataTime: \"08-21\"},\n" +
"{\n" +
"dataDetail:[\n" +
"{xcm: \"20cm\",dataV: 20.00},\n" +
"{xcm: \"40cm\",dataV: 21.00},\n" +
"{xcm: \"60cm\",dataV: 22.00},\n" +
"{xcm: \"80cm\",dataV: 23.00},\n" +
"{xcm: \"100cm\",dataV: 26.00},\n" +
"{xcm: \"120cm\",dataV: 24.00},\n" +
"{xcm: \"150cm\",dataV: 25.00}],\n" +
"dataTime: \"08-23\"},\n" +
"{\n" +
"dataDetail:[\n" +
"{xcm: \"20cm\",dataV: 30.00},\n" +
"{xcm: \"40cm\",dataV: 31.00},\n" +
"{xcm: \"60cm\",dataV: 32.00},\n" +
"{xcm: \"80cm\",dataV: 33.00},\n" +
"{xcm: \"100cm\",dataV: 36.00},\n" +
"{xcm: \"120cm\",dataV: 34.00},\n" +
"{xcm: \"150cm\",dataV: 35.00}],\n" +
"dataTime: \"08-25\"},\n" +
"{\n" +
"dataDetail:[\n" +
"{xcm: \"20cm\",dataV: 40.00},\n" +
"{xcm: \"40cm\",dataV: 41.00},\n" +
"{xcm: \"60cm\",dataV: 42.00},\n" +
"{xcm: \"80cm\",dataV: 43.00},\n" +
"{xcm: \"100cm\",dataV: 46.00},\n" +
"{xcm: \"120cm\",dataV: 44.00},\n" +
"{xcm: \"150cm\",dataV: 45.00}],\n" +
"dataTime: \"08-27\"}\n" +
"],\n" +
"code: 1\n" +
"}";
@Override
protected void lazyLoad() {
if (!isPrepared || !isVisible) {
return;
}
LogUtils.e("TAG","SoilmoistureHistoryFragment--lazyLoad");
initDateSelect();
initMonitorIndexSelect();
//
getData("d","default");
}
}