封装一个MVP架构的基类

SuperCalendar是一个日历控件,在使用它时,如果calendarAdapter.setMarkData(markData);被调用了两次就出现问题了,会导致第二次设置的map覆盖掉第一次设置的Map

问题

它给的例子是这样的:

private void initMarkData() {
        HashMap<String,String> markData=new HashMap<>();
        //1的时候是灰色,0的时候是亮色
        markData.put("2018-6-1", "1");
        markData.put("2018-6-2", "1");
        markData.put("2018-6-3", "0");
        markData.put("2018-6-4", "0");

        markData.put("2018-7-5", "0");
        markData.put("2018-7-6", "1");
        markData.put("2018-7-7", "1");

        calendarAdapter.setMarkData(markData);
    }

加入我们有这个场景,联网获取每一个月的标记数据,然后标记上,那么这个方法的调用肯定不止一次,所以在请求网络结束后需要调用以下方法来更新标记:
(不要调用notifyDataChanged(),这一点文档有误,否则会报空指针)

//1的时候是灰色,0的时候是亮色
        HashMap<String,String> markData=new HashMap<>();
        markData.put("2018-6-9", "0");
        markData.put("2018-6-10", "0");

        markData.put("2018-7-10", "0");
        markData.put("2018-7-11", "0");
        markData.put("2018-7-12", "1");

        calendarAdapter.setMarkData(markData);
    }

等等,运行后,你会发现第一次的数据没有了,为什么呢?

只有一个原因,那就是我们第二次设置markData后把第一次覆盖掉了,也就是说第二次设置的这个Map引用覆盖掉了第一次设置的Map引用。

通过代码跟进,发现:CalendarViewAdapter.java

public void setMarkData(HashMap<String, String> markData) {
        Utils.setMarkData(markData);
    }

继续跟进:Utils.java

public static void setMarkData(HashMap<String, String> data) {
        markData = data;
    }

果然,它是直接修改了这个引用,所以第二次肯定覆盖掉第一次设置的值

解决办法

方法1:本来我是想看一下它有没有getMarkData()这类的方法,如果有的话我们只需要将新的Map追加到旧的Map中即可,未果

方法2:我们的本意是每次添加markData时不修改HashMap的引用,那么只要维护一个HashMap即可,不管第几次添加mark,都添加到该HashMap

例如:

  • 设置一个全局的HashMap
public HashMap<String, String> markData=new HashMap<>();
  • 然后设置markData即可
/**
     * 初始化标记数据
     */
    private void initMarkData() {
        //1的时候是灰色,0的时候是亮色
        markData.put("2018-6-1", "1");
        markData.put("2018-6-2", "1");
        markData.put("2018-6-3", "0");
        markData.put("2018-6-4", "0");

        markData.put("2018-7-5", "0");
        markData.put("2018-7-6", "1");
        markData.put("2018-7-7", "1");

        calendarAdapter.setMarkData(markData);
    }

    /**
     * 刘壮飞
     *
     * 这里模拟的是第二次setMarkData(markData)的情景
     *
     * 我们维护一个Map,注意不要修改该Map的引用
     * 可以使用clear(),不要用markData=new HashMap<>();
     */
    public void initMarkDataAfter(){
        //1的时候是灰色,0的时候是亮色
        markData.put("2018-6-9", "0");
        markData.put("2018-6-10", "0");

        markData.put("2018-7-10", "0");
        markData.put("2018-7-11", "0");
        markData.put("2018-7-12", "1");

        calendarAdapter.setMarkData(markData);
    }

完整的代码

大功告成了!!!

以下是MainActivity的完整代码,其他代码与项目中给的example完全一致,此代码中只有添加了刘壮飞标记的才是我添加的部分,已在上文列出

package com.zhuangfei.calenderdemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.ldf.calendar.Utils;
import com.ldf.calendar.component.CalendarAttr;
import com.ldf.calendar.view.MonthPager;
import com.ldf.calendar.interf.OnSelectDateListener;
import com.ldf.calendar.component.CalendarViewAdapter;
import com.ldf.calendar.model.CalendarDate;
import com.ldf.calendar.view.Calendar;
import com.zhuangfei.calenderdemo.CustomDayView;
import com.zhuangfei.calenderdemo.R;
import com.zhuangfei.calenderdemo.ThemeDayView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ldf on 16/11/4.
 */

@SuppressLint("SetTextI18n")
public class MainActivity extends AppCompatActivity {
    TextView tvYear;
    TextView tvMonth;
    TextView backToday;
    CoordinatorLayout content;
    MonthPager monthPager;
    RecyclerView rvToDoList;
    TextView scrollSwitch;
    TextView themeSwitch;
    TextView nextMonthBtn;
    TextView lastMonthBtn;

    private ArrayList<Calendar> currentCalendars = new ArrayList<>();
    private CalendarViewAdapter calendarAdapter;
    private OnSelectDateListener onSelectDateListener;
    private int mCurrentPage = MonthPager.CURRENT_DAY_INDEX;
    private Context context;
    private CalendarDate currentDate;
    private boolean initiated = false;


    /**
     * 刘壮飞
     */
    public HashMap<String, String> markData=new HashMap<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        content = (CoordinatorLayout) findViewById(R.id.content);
        monthPager = (MonthPager) findViewById(R.id.calendar_view);
        //此处强行setViewHeight,毕竟你知道你的日历牌的高度
        monthPager.setViewHeight(Utils.dpi2px(context, 270));
        tvYear = (TextView) findViewById(R.id.show_year_view);
        tvMonth = (TextView) findViewById(R.id.show_month_view);
        backToday = (TextView) findViewById(R.id.back_today_button);
        scrollSwitch = (TextView) findViewById(R.id.scroll_switch);
        themeSwitch = (TextView) findViewById(R.id.theme_switch);
        nextMonthBtn = (TextView) findViewById(R.id.next_month);
        lastMonthBtn = (TextView) findViewById(R.id.last_month);
        rvToDoList = (RecyclerView) findViewById(R.id.list);
        rvToDoList.setHasFixedSize(true);
        //这里用线性显示 类似于listview
        rvToDoList.setLayoutManager(new LinearLayoutManager(this));
        rvToDoList.setAdapter(new ExampleAdapter(this));
        initCurrentDate();
        initCalendarView();
        initToolbarClickListener();
        Log.e("ldf","OnCreated");

        initMarkDataAfter();
    }

    /**
     * onWindowFocusChanged回调时,将当前月的种子日期修改为今天
     *
     * @return void
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && !initiated) {
            refreshMonthPager();
            initiated = true;
        }
    }

    /*
    * 如果你想以周模式启动你的日历,请在onResume是调用
    * Utils.scrollTo(content, rvToDoList, monthPager.getCellHeight(), 200);
    * calendarAdapter.switchToWeek(monthPager.getRowIndex());
    * */
    @Override
    protected void onResume() {
        super.onResume();
    }

    /**
     * 初始化对应功能的listener
     *
     * @return void
     */
    private void initToolbarClickListener() {
        backToday.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onClickBackToDayBtn();
            }
        });
        scrollSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (calendarAdapter.getCalendarType() == CalendarAttr.CalendarType.WEEK) {
                    Utils.scrollTo(content, rvToDoList, monthPager.getViewHeight(), 200);
                    calendarAdapter.switchToMonth();
                } else {
                    Utils.scrollTo(content, rvToDoList, monthPager.getCellHeight(), 200);
                    calendarAdapter.switchToWeek(monthPager.getRowIndex());
                }
            }
        });
        themeSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                refreshSelectBackground();
            }
        });
        nextMonthBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                monthPager.setCurrentItem(monthPager.getCurrentPosition() + 1);
            }
        });
        lastMonthBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                monthPager.setCurrentItem(monthPager.getCurrentPosition() - 1);
            }
        });
    }

    /**
     * 初始化currentDate
     *
     * @return void
     */
    private void initCurrentDate() {
        currentDate = new CalendarDate();
        tvYear.setText(currentDate.getYear() + "年");
        tvMonth.setText(currentDate.getMonth() + "");
    }

    /**
     * 初始化CustomDayView,并作为CalendarViewAdapter的参数传入
     */
    private void initCalendarView() {
        initListener();
        CustomDayView customDayView = new CustomDayView(context, R.layout.custom_day);
        calendarAdapter = new CalendarViewAdapter(
                context,
                onSelectDateListener,
                CalendarAttr.CalendarType.MONTH,
                CalendarAttr.WeekArrayType.Monday,
                customDayView);
        calendarAdapter.setOnCalendarTypeChangedListener(new CalendarViewAdapter.OnCalendarTypeChanged() {
            @Override
            public void onCalendarTypeChanged(CalendarAttr.CalendarType type) {
                rvToDoList.scrollToPosition(0);
            }
        });
        initMarkData();
        initMonthPager();
    }

    /**
     * 初始化标记数据,HashMap的形式,可自定义
     * 如果存在异步的话,在使用setMarkData之后调用 calendarAdapter.notifyDataChanged();
     */
    private void initMarkData() {
        HashMap<String,String> markData=new HashMap<>();
        //1的时候是灰色,0的时候是亮色
        markData.put("2018-6-1", "1");
        markData.put("2018-6-2", "1");
        markData.put("2018-6-3", "0");
        markData.put("2018-6-4", "0");

        markData.put("2018-7-5", "0");
        markData.put("2018-7-6", "1");
        markData.put("2018-7-7", "1");

        calendarAdapter.setMarkData(markData);
    }

    /**
     * 刘壮飞
     *
     * 这里模拟的是第二次setMarkData(markData)的情景
     *
     * 我们维护一个Map,注意不要修改该Map的引用
     * 可以使用clear(),不要用markData=new HashMap<>();
     */
    public void initMarkDataAfter(){
        //1的时候是灰色,0的时候是亮色
        markData.put("2018-6-9", "0");
        markData.put("2018-6-10", "0");

        markData.put("2018-7-10", "0");
        markData.put("2018-7-11", "0");
        markData.put("2018-7-12", "1");

        calendarAdapter.setMarkData(markData);
    }

    private void initListener() {
        onSelectDateListener = new OnSelectDateListener() {
            @Override
            public void onSelectDate(CalendarDate date) {
                refreshClickDate(date);
            }

            @Override
            public void onSelectOtherMonth(int offset) {
                //偏移量 -1表示刷新成上一个月数据 , 1表示刷新成下一个月数据
                monthPager.selectOtherMonth(offset);
            }
        };
    }


    private void refreshClickDate(CalendarDate date) {
        currentDate = date;
        tvYear.setText(date.getYear() + "年");
        tvMonth.setText(date.getMonth() + "");
    }

    /**
     * 初始化monthPager,MonthPager继承自ViewPager
     *
     * @return void
     */
    private void initMonthPager() {
        monthPager.setAdapter(calendarAdapter);
        monthPager.setCurrentItem(MonthPager.CURRENT_DAY_INDEX);
        monthPager.setPageTransformer(false, new ViewPager.PageTransformer() {
            @Override
            public void transformPage(View page, float position) {
                position = (float) Math.sqrt(1 - Math.abs(position));
                page.setAlpha(position);
            }
        });
        monthPager.addOnPageChangeListener(new MonthPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                mCurrentPage = position;
                currentCalendars = calendarAdapter.getPagers();
                if (currentCalendars.get(position % currentCalendars.size()) != null) {
                    CalendarDate date = currentCalendars.get(position % currentCalendars.size()).getSeedDate();
                    currentDate = date;
                    tvYear.setText(date.getYear() + "年");
                    tvMonth.setText(date.getMonth() + "");
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    public void onClickBackToDayBtn() {
        refreshMonthPager();
    }

    private void refreshMonthPager() {
        CalendarDate today = new CalendarDate();
        calendarAdapter.notifyDataChanged(today);
        tvYear.setText(today.getYear() + "年");
        tvMonth.setText(today.getMonth() + "");
    }

    private void refreshSelectBackground() {
        ThemeDayView themeDayView = new ThemeDayView(context, R.layout.custom_day_focus);
        calendarAdapter.setCustomDayRenderer(themeDayView);
        calendarAdapter.notifyDataSetChanged();
        calendarAdapter.notifyDataChanged(new CalendarDate());
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值