我正在尝试在Android应用中构建月度日历。我的应用使用MainActivity
,NavigationDrawer
和Fragments
。显示日历的片段称为MonthCalendar
。
GridView
用于显示日历。
我的适配器基于droidwalk implementation。
我的目标是每天显示一个ImageView和一个TextBox(日期编号)。我从Web服务获取日期数据并将这些数据存储在SQLite数据库中。
MonthFragment.java
public class MonthFragment extends BaseFragment {
public GridView gridview;
public GregorianCalendar month, itemmonth;
public CalendarAdapter adapter;
public Handler handler;
private DayRepository dayRepository;
private List<Day> days;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_month, null);
Locale.setDefault(Locale.FRANCE);
month = (GregorianCalendar) GregorianCalendar.getInstance();
// Prepare the DB repository
this.dayRepository = new DayRepository();
...
adapter = new CalendarAdapter(view.getContext(), month);
adapter.notifyDataSetChanged();
gridview = (GridView) view.findViewById(R.id.gridView_month);
gridview.setAdapter(adapter);
// Handler
days = new ArrayList<Day>();
handler = new Handler();
handler.post(calendarUpdater);
// Click event next/prev button call refreshCalendar()
...
return view;
}
...
public void refreshCalendar() {
TextView title = (TextView) getActivity().findViewById(R.id.title);
gridview.invalidateViews();
adapter.refreshDays();
adapter.notifyDataSetChanged();
handler.post(calendarUpdater);
String monthTitle = (String) android.text.format.DateFormat.format("MMMM yyyy", month);
title.setText(monthTitle.substring(0,1).toUpperCase() + monthTitle.substring(1));
}
public Runnable calendarUpdater = new Runnable() {
@Override
public void run() {
days.clear();
// Fetch data from SQLlite DB
days = dayRepository.getByMonth(month.get(GregorianCalendar.MONTH)+1, month.get(GregorianCalendar.YEAR));
adapter.setDays(days);
adapter.notifyDataSetChanged();
}
};
}
CalendarAdapter.java
public class CalendarAdapter extends BaseAdapter {
private Context mContext;
private Calendar month;
public GregorianCalendar pmonth;
public GregorianCalendar pmonthmaxset;
private GregorianCalendar selectedDate;
private int firstDay;
private int maxWeeknumber;
private int maxP;
private int calMaxP;
private int lastWeekDay;
private int leftDays;
private int mnthlength;
private String itemvalue, curentDateString;
private DateFormat df;
public static List<String> dayString;
private View previousView;
private List<Day> days;
public CalendarAdapter(Context c, GregorianCalendar monthCalendar) {
CalendarAdapter.dayString = new ArrayList<String>();
month = monthCalendar;
selectedDate = (GregorianCalendar) monthCalendar.clone();
mContext = c;
month.set(GregorianCalendar.DAY_OF_MONTH, 1);
this.days = new ArrayList<Day>();
df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
curentDateString = df.format(selectedDate.getTime());
refreshDays();
}
public void setDays(List<Day> days) {
this.days = days;
}
public int getCount() {
return dayString.size();
}
public Object getItem(int position) {
return dayString.get(position);
}
public long getItemId(int position) {
return 0;
}
// Create a new view for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
// Keeps reference to avoid future findViewById()
CalendarViewHolder holder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.calendar_item, null);
holder = new CalendarViewHolder();
holder.dayImg = (ImageView) view.findViewById(R.id.date_img);
holder.dayDescription = (TextView) view.findViewById(R.id.date_desc);
holder.dayNumber = (TextView) view.findViewById(R.id.date);
holder.rl_gridDay = (RelativeLayout) view.findViewById(R.id.relativeLayout_gridDay);
view.setTag(holder);
} else {
holder = (CalendarViewHolder) view.getTag();
}
String[] separatedTime = dayString.get(position).split("-");
String gridvalue = separatedTime[2].replaceFirst("^0*", "");
Log.d("Calendar", "===============> getView() call " + gridvalue);
// Day is in current month?
if ((Integer.parseInt(gridvalue) > 1) && (position < firstDay)) {
// Offdays (before month)
holder.dayNumber.setClickable(false);
holder.dayNumber.setFocusable(false);
holder.rl_gridDay.setVisibility(View.INVISIBLE);
} else if ((Integer.parseInt(gridvalue) < 7) && (position > 28)) {
// Offdays (after month)
holder.dayNumber.setClickable(false);
holder.dayNumber.setFocusable(false);
holder.rl_gridDay.setVisibility(View.INVISIBLE);
} else {
holder.dayNumber.setTextColor(Color.WHITE);
holder.rl_gridDay.setVisibility(View.VISIBLE);
}
if (dayString.get(position).equals(curentDateString)) {
setSelected(view);
previousView = view;
} else {
view.setBackgroundResource(R.drawable.list_item_background);
}
holder.dayNumber.setText(gridvalue);
// START
Day currentDay = null;
if (date.length() > 0 && days != null) {
for (Day object : days) {
if (object.getMday() == Integer.parseInt(gridvalue)) {
currentDay = object;
break;
}
}
} else {
holder.dayImg.setVisibility(View.INVISIBLE);
holder.constellation.setVisibility(View.INVISIBLE);
holder.dayDescription.setVisibility(View.INVISIBLE);
}
if (currentDay != null) {
DayUtil dayUtil = new DayUtil(currentDay, mContext);
holder.dayImg.setImageResource(dayUtil.getDrawableId());
holder.dayDescription.setText(dayUtil.formatDesc());
holder.dayImg.setVisibility(View.VISIBLE);
holder.dayDescription.setVisibility(View.VISIBLE);
}
// END
return view;
}
public View setSelected(View view) {
if (previousView != null) {
previousView.setBackgroundResource(R.drawable.list_item_background);
}
previousView = view;
view.setBackgroundResource(R.drawable.calendar_cell_select);
return view;
}
public void refreshDays() {
days.clear();
dayString.clear();
pmonth = (GregorianCalendar) month.clone();
// month start day. ie; sun, mon, etc
firstDay = month.get(GregorianCalendar.DAY_OF_WEEK);
// finding number of weeks in current month.
maxWeeknumber = month.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH);
if(maxWeeknumber >= 6) maxWeeknumber = 5;
// allocating maximum row number for the gridview.
mnthlength = maxWeeknumber * 7;
maxP = getMaxP(); // previous month maximum day 31,30....
calMaxP = maxP - (firstDay - 1);// calendar offday starting 24,25 ...
pmonthmaxset = (GregorianCalendar) pmonth.clone();
pmonthmaxset.set(GregorianCalendar.DAY_OF_MONTH, calMaxP + 1);
/**
* filling calendar gridview.
*/
for (int n = 0; n < mnthlength; n++) {
itemvalue = df.format(pmonthmaxset.getTime());
pmonthmaxset.add(GregorianCalendar.DATE, 1);
dayString.add(itemvalue);
}
}
private int getMaxP() {
int maxP;
if (month.get(GregorianCalendar.MONTH) == month.getActualMinimum(GregorianCalendar.MONTH)) {
pmonth.set((month.get(GregorianCalendar.YEAR) - 1), month.getActualMaximum(GregorianCalendar.MONTH), 1);
} else {
pmonth.set(GregorianCalendar.MONTH, month.get(GregorianCalendar.MONTH) - 1);
}
maxP = pmonth.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
return maxP;
}
public static class CalendarViewHolder {
public ImageView dayImg;
public TextView dayDescription;
public RelativeLayout rl_gridDay;
public TextView dayNumber;
}
}
DayUtil.java
public class DayUtil {
private Day day;
private Context context;
...
/**
* Return the day image picture ID
* Dynamic loading of images R.Drawable depending on a day parameter
*/
public int getDrawable() {
...
return context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
}
}
GridView
类过度调用适配器的getView()
方法(或多或少70次)。主UI冻结几秒钟,加载速度非常慢。
我试图将// START
和// END
行之间的操作放在AsyncTask
中,但没有任何改进。
logcat的
01-25 17:07:56.132 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:56.140 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:56.140 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
01-25 17:07:56.144 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
01-25 17:07:56.148 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
01-25 17:07:56.152 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 2
01-25 17:07:56.152 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 3
01-25 17:07:56.156 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 4
01-25 17:07:56.160 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 5
01-25 17:07:56.160 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 6
01-25 17:07:56.168 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 7
01-25 17:07:56.172 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 8
01-25 17:07:56.176 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 9
01-25 17:07:56.180 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 10
01-25 17:07:56.184 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 11
01-25 17:07:56.188 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 12
01-25 17:07:56.188 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 13
01-25 17:07:56.192 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 14
01-25 17:07:56.196 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 15
01-25 17:07:56.200 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 16
01-25 17:07:56.204 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 17
01-25 17:07:56.204 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 18
01-25 17:07:56.208 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 19
01-25 17:07:56.208 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 20
01-25 17:07:56.212 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 21
01-25 17:07:56.216 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 22
01-25 17:07:56.216 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 23
01-25 17:07:56.220 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 24
01-25 17:07:56.224 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 25
01-25 17:07:56.228 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 26
01-25 17:07:56.232 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 27
01-25 17:07:56.232 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 28
01-25 17:07:56.236 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:56.240 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
01-25 17:07:56.240 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
01-25 17:07:56.244 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
01-25 17:07:56.332 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:56.340 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:56.344 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
01-25 17:07:56.356 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
01-25 17:07:56.356 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
01-25 17:07:56.360 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 2
01-25 17:07:56.360 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 3
01-25 17:07:56.364 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 4
01-25 17:07:56.372 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 416K, 4% free 16135K/16752K, paused 8ms, total 9ms
01-25 17:07:56.416 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 5
01-25 17:07:56.452 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 4955K, 31% free 12739K/18312K, paused 7ms, total 7ms
01-25 17:07:56.464 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 6
01-25 17:07:56.492 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 7
01-25 17:07:56.520 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 8
01-25 17:07:56.528 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 11K, 21% free 14473K/18312K, paused 8ms, total 8ms
01-25 17:07:56.556 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 9
01-25 17:07:56.584 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 10
01-25 17:07:56.596 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 7K, 13% free 16029K/18312K, paused 9ms, total 9ms
01-25 17:07:56.628 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 11
01-25 17:07:56.664 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 12
01-25 17:07:56.672 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 7K, 4% free 17585K/18312K, paused 7ms, total 7ms
01-25 17:07:56.704 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 13
01-25 17:07:56.712 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 18363K/19092K, paused 8ms, total 8ms
01-25 17:07:56.744 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 14
01-25 17:07:56.752 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 19141K/19872K, paused 8ms, total 8ms
01-25 17:07:56.784 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 15
01-25 17:07:56.788 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 19919K/20652K, paused 6ms, total 6ms
01-25 17:07:56.820 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 16
01-25 17:07:56.820 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 17
01-25 17:07:56.832 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 4% free 20698K/21432K, paused 9ms, total 9ms
01-25 17:07:56.864 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 18
01-25 17:07:56.872 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 21476K/22212K, paused 5ms, total 6ms
01-25 17:07:56.904 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 19
01-25 17:07:56.912 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 22254K/22992K, paused 7ms, total 7ms
01-25 17:07:56.940 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 20
01-25 17:07:56.948 3243-3243/com.example.android D/dalvikvm﹕ GC_FOR_ALLOC freed 3K, 4% free 23032K/23772K, paused 6ms, total 6ms
01-25 17:07:56.980 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 21
01-25 17:07:57.024 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 22
01-25 17:07:57.068 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 23
01-25 17:07:57.104 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 24
01-25 17:07:57.140 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 25
01-25 17:07:57.140 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 26
01-25 17:07:57.180 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 27
01-25 17:07:57.212 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 28
01-25 17:07:57.212 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 29
01-25 17:07:57.212 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 30
01-25 17:07:57.216 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 31
01-25 17:07:57.216 3243-3243/com.example.android D/Calendar﹕ ===============> getView() call 1
scrollingCache="false"
不更改(see idea here) 我做错了吗? 你能救我吗?
谢谢!