Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java

Issue 2670083002: [Download Home] Displaying offline page bundle per day (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.widget; 5 package org.chromium.chrome.browser.widget;
6 6
7 import android.os.AsyncTask; 7 import android.os.AsyncTask;
8 import android.support.v7.widget.RecyclerView; 8 import android.support.v7.widget.RecyclerView;
9 import android.support.v7.widget.RecyclerView.Adapter; 9 import android.support.v7.widget.RecyclerView.Adapter;
10 import android.support.v7.widget.RecyclerView.ViewHolder; 10 import android.support.v7.widget.RecyclerView.ViewHolder;
11 import android.text.format.DateUtils; 11 import android.text.format.DateUtils;
12 import android.util.Pair; 12 import android.util.Pair;
13 import android.view.LayoutInflater; 13 import android.view.LayoutInflater;
14 import android.view.View; 14 import android.view.View;
15 import android.view.ViewGroup; 15 import android.view.ViewGroup;
16 import android.widget.TextView; 16 import android.widget.TextView;
17 17
18 import org.chromium.chrome.R; 18 import org.chromium.chrome.R;
19 import org.chromium.chrome.browser.widget.DateDividedAdapter.ItemGroup;
20 19
21 import java.util.ArrayList; 20 import java.util.ArrayList;
22 import java.util.Calendar; 21 import java.util.Calendar;
23 import java.util.Collections; 22 import java.util.Collections;
24 import java.util.Comparator; 23 import java.util.Comparator;
25 import java.util.Date; 24 import java.util.Date;
26 import java.util.List; 25 import java.util.List;
27 import java.util.SortedSet; 26 import java.util.SortedSet;
28 import java.util.TreeSet; 27 import java.util.TreeSet;
29 import java.util.concurrent.ExecutionException; 28 import java.util.concurrent.ExecutionException;
(...skipping 13 matching lines...) Expand all
43 * Interface that the {@link Adapter} uses to interact with the items it man ages. 42 * Interface that the {@link Adapter} uses to interact with the items it man ages.
44 */ 43 */
45 public abstract static class TimedItem { 44 public abstract static class TimedItem {
46 /** Value indicating that a TimedItem is not currently being displayed. */ 45 /** Value indicating that a TimedItem is not currently being displayed. */
47 public static final int INVALID_POSITION = -1; 46 public static final int INVALID_POSITION = -1;
48 47
49 /** Position of the TimedItem in the list, or {@link #INVALID_POSITION} if not shown. */ 48 /** Position of the TimedItem in the list, or {@link #INVALID_POSITION} if not shown. */
50 private int mPosition = INVALID_POSITION; 49 private int mPosition = INVALID_POSITION;
51 50
52 /** See {@link #mPosition}. */ 51 /** See {@link #mPosition}. */
53 private final void setPosition(int position) { 52 public final void setPosition(int position) {
54 mPosition = position; 53 mPosition = position;
55 } 54 }
56 55
57 /** See {@link #mPosition}. */ 56 /** See {@link #mPosition}. */
58 public final int getPosition() { 57 public final int getPosition() {
59 return mPosition; 58 return mPosition;
60 } 59 }
61 60
62 /** @return The timestamp for this item. */ 61 /** @return The timestamp for this item. */
63 public abstract long getTimestamp(); 62 public abstract long getTimestamp();
64 63
65 /** 64 /**
66 * Returns an ID that uniquely identifies this TimedItem and doesn't cha nge. 65 * Returns an ID that uniquely identifies this TimedItem and doesn't cha nge.
67 * To avoid colliding with IDs generated for Date headers, at least one of the upper 32 66 * To avoid colliding with IDs generated for Date headers, at least one of the upper 32
68 * bits of the long should be set. 67 * bits of the long should be set.
69 * @return ID that can uniquely identify the TimedItem. 68 * @return ID that can uniquely identify the TimedItem.
70 */ 69 */
71 public abstract long getStableId(); 70 public abstract long getStableId();
71
72 /** @return Whether this item is an offline page. */
73 public boolean isOfflinePage() {
gone 2017/02/02 20:49:55 This class should really have no idea what an offl
shaktisahu 2017/02/02 23:29:38 Okay. In that case, I can move this function to Do
74 return false;
75 }
72 } 76 }
73 77
74 private static class DateViewHolder extends RecyclerView.ViewHolder { 78 private static class DateViewHolder extends RecyclerView.ViewHolder {
75 private TextView mTextView; 79 private TextView mTextView;
76 80
77 public DateViewHolder(View view) { 81 public DateViewHolder(View view) {
78 super(view); 82 super(view);
79 if (view instanceof TextView) mTextView = (TextView) view; 83 if (view instanceof TextView) mTextView = (TextView) view;
80 } 84 }
81 85
(...skipping 26 matching lines...) Expand all
108 112
109 protected static class BasicViewHolder extends RecyclerView.ViewHolder { 113 protected static class BasicViewHolder extends RecyclerView.ViewHolder {
110 public BasicViewHolder(View itemView) { 114 public BasicViewHolder(View itemView) {
111 super(itemView); 115 super(itemView);
112 } 116 }
113 } 117 }
114 118
115 /** 119 /**
116 * A bucket of items with the same date. 120 * A bucket of items with the same date.
117 */ 121 */
118 protected static class ItemGroup { 122 public static class ItemGroup {
119 private final Date mDate; 123 private final Date mDate;
120 private final List<TimedItem> mItems = new ArrayList<>(); 124 protected final List<TimedItem> mItems = new ArrayList<>();
121 125
122 /** Index of the header, relative to the full list. Must be set only on ce.*/ 126 /** Index of the header, relative to the full list. Must be set only on ce.*/
123 private int mIndex; 127 private int mIndex;
124 128
125 private boolean mIsSorted; 129 private boolean mIsSorted;
126 private boolean mIsListHeaderOrFooter; 130 private boolean mIsListHeaderOrFooter;
127 131
128 public ItemGroup(long timestamp) { 132 public ItemGroup(long timestamp) {
129 mDate = new Date(timestamp); 133 mDate = new Date(timestamp);
130 mIsSorted = true; 134 mIsSorted = true;
131 } 135 }
132 136
133 public void addItem(TimedItem item) { 137 public void addItem(TimedItem item) {
134 mItems.add(item); 138 mItems.add(item);
135 mIsSorted = mItems.size() == 1; 139 mIsSorted = mItems.size() == 1;
136 } 140 }
137 141
138 public void removeItem(TimedItem item) { 142 public void removeItem(TimedItem item) {
139 mItems.remove(item); 143 mItems.remove(item);
140 } 144 }
141 145
142 /** Records the position of all the TimedItems in this group, relative t o the full list. */ 146 /** Records the position of all the TimedItems in this group, relative t o the full list. */
143 public void setPosition(int index) { 147 public void setPosition(int index) {
144 assert mIndex == 0 || mIndex == TimedItem.INVALID_POSITION; 148 assert mIndex == 0 || mIndex == TimedItem.INVALID_POSITION;
145 mIndex = index; 149 mIndex = index;
146 150
147 sortIfNeeded(); 151 sortIfNeeded();
152 setPositionForItems(index + 1);
153 }
154
155 protected void setPositionForItems(int startIndex) {
156 int index = startIndex;
148 for (TimedItem item : mItems) { 157 for (TimedItem item : mItems) {
158 item.setPosition(index);
149 index += 1; 159 index += 1;
150 item.setPosition(index);
151 } 160 }
152 } 161 }
153 162
154 /** Unsets the position of all TimedItems in this group. */ 163 /** Unsets the position of all TimedItems in this group. */
155 public void resetPosition() { 164 public void resetPosition() {
156 mIndex = TimedItem.INVALID_POSITION; 165 mIndex = TimedItem.INVALID_POSITION;
157 for (TimedItem item : mItems) item.setPosition(TimedItem.INVALID_POS ITION); 166 for (TimedItem item : mItems) item.setPosition(TimedItem.INVALID_POS ITION);
158 } 167 }
159 168
160 /** 169 /**
161 * @return Whether the given date happens in the same day as the items i n this group. 170 * @return Whether the given date happens in the same day as the items i n this group.
162 */ 171 */
163 public boolean isSameDay(Date otherDate) { 172 public boolean isSameDay(Date otherDate) {
164 return compareDate(mDate, otherDate) == 0; 173 return compareDate(mDate, otherDate) == 0;
165 } 174 }
166 175
167 /** 176 protected boolean isListHeaderOrFooter() {
168 * @return The size of this group. 177 return mIsListHeaderOrFooter;
169 */ 178 }
gone 2017/02/02 23:59:48 Why'd you remove this?
shaktisahu 2017/02/04 18:57:43 Done. Was accidentally removed.
179
180 protected Date getDate() {
181 return mDate;
182 }
183
170 public int size() { 184 public int size() {
171 if (mIsListHeaderOrFooter) return 1; 185 if (mIsListHeaderOrFooter) return 1;
172 186
173 // Plus 1 to account for the date header. 187 // Plus 1 to account for the date header.
174 return mItems.size() + 1; 188 return mItems.size() + 1;
175 } 189 }
176 190
177 public TimedItem getItemAt(int index) { 191 public TimedItem getItemAt(int index) {
178 // 0 is allocated to the date header. The list header has no items. 192 // 0 is allocated to the date header. The list header has no items.
179 if (index == 0 || mIsListHeaderOrFooter) return null; 193 if (index == 0 || mIsListHeaderOrFooter) return null;
180 194
181 sortIfNeeded(); 195 sortIfNeeded();
182 return mItems.get(index - 1); 196 return mItems.get(index - 1);
183 } 197 }
184 198
185 /** 199 /**
186 * Rather than sorting the list each time a new item is added, the list is sorted when 200 * Rather than sorting the list each time a new item is added, the list is sorted when
187 * something requires a correct ordering of the items. 201 * something requires a correct ordering of the items.
188 */ 202 */
189 private void sortIfNeeded() { 203 protected void sortIfNeeded() {
190 if (mIsSorted) return; 204 if (mIsSorted) return;
191 mIsSorted = true; 205 mIsSorted = true;
192 206
193 Collections.sort(mItems, new Comparator<TimedItem>() { 207 Collections.sort(mItems, new Comparator<TimedItem>() {
194 @Override 208 @Override
195 public int compare(TimedItem lhs, TimedItem rhs) { 209 public int compare(TimedItem lhs, TimedItem rhs) {
196 // More recent items are listed first. Ideally we'd use Lon g.compare, but that 210 return compareItem(lhs, rhs);
197 // is an API level 19 call for some inexplicable reason.
198 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
199 if (timeDelta > 0) {
200 return -1;
201 } else if (timeDelta == 0) {
202 return 0;
203 } else {
204 return 1;
205 }
206 } 211 }
207 }); 212 });
208 } 213 }
214
215 protected int compareItem(TimedItem lhs, TimedItem rhs) {
216 // More recent items are listed first. Ideally we'd use Long.compar e, but that
217 // is an API level 19 call for some inexplicable reason.
218 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
219 if (timeDelta > 0) {
220 return -1;
221 } else if (timeDelta == 0) {
222 return 0;
223 } else {
224 return 1;
225 }
226 }
227
228 public int getItemViewType(int position) {
229 return TYPE_NORMAL;
230 }
209 } 231 }
210 232
211 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates. 233 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates.
212 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( ); 234 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( );
213 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( ); 235 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( );
214 236
215 public static final int TYPE_FOOTER = -2; 237 public static final int TYPE_FOOTER = -2;
216 public static final int TYPE_HEADER = -1; 238 public static final int TYPE_HEADER = -1;
217 public static final int TYPE_DATE = 0; 239 public static final int TYPE_DATE = 0;
218 public static final int TYPE_NORMAL = 1; 240 public static final int TYPE_NORMAL = 1;
241 public static final int TYPE_OFFLINE_HEADER = 2;
gone 2017/02/02 23:59:48 automatic offline header or something
shaktisahu 2017/02/04 18:57:43 Done. TYPE_SUGGESTED_OFFLINE_PAGES_HEADER
219 242
220 private int mSize; 243 private int mSize;
221 private boolean mHasListHeader; 244 private boolean mHasListHeader;
222 private boolean mHasListFooter; 245 private boolean mHasListFooter;
223 246
224 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() { 247 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() {
225 @Override 248 @Override
226 public int compare(ItemGroup lhs, ItemGroup rhs) { 249 public int compare(ItemGroup lhs, ItemGroup rhs) {
227 return compareDate(lhs.mDate, rhs.mDate); 250 return compareDate(lhs.mDate, rhs.mDate);
228 } 251 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 * {@link #clear(boolean)} to remove previous items. 290 * {@link #clear(boolean)} to remove previous items.
268 */ 291 */
269 public void loadItems(List<? extends TimedItem> timedItems) { 292 public void loadItems(List<? extends TimedItem> timedItems) {
270 for (TimedItem timedItem : timedItems) { 293 for (TimedItem timedItem : timedItems) {
271 Date date = new Date(timedItem.getTimestamp()); 294 Date date = new Date(timedItem.getTimestamp());
272 boolean found = false; 295 boolean found = false;
273 for (ItemGroup group : mGroups) { 296 for (ItemGroup group : mGroups) {
274 if (group.isSameDay(date)) { 297 if (group.isSameDay(date)) {
275 found = true; 298 found = true;
276 group.addItem(timedItem); 299 group.addItem(timedItem);
277 mSize++;
278 break; 300 break;
279 } 301 }
280 } 302 }
281 if (!found) { 303 if (!found) {
282 // Create a new ItemGroup with the date for the new item. This i ncreases the 304 // Create a new ItemGroup with the date for the new item. This i ncreases the
283 // size by two because we add new views for the date and the ite m itself. 305 // size by two because we add new views for the date and the ite m itself.
284 ItemGroup newGroup = new ItemGroup(timedItem.getTimestamp()); 306 ItemGroup newGroup = createGroup(timedItem.getTimestamp());
285 newGroup.addItem(timedItem); 307 newGroup.addItem(timedItem);
286 mGroups.add(newGroup); 308 mGroups.add(newGroup);
287 mSize += 2;
288 } 309 }
289 } 310 }
290 311
312 computeItemCount();
291 setGroupPositions(); 313 setGroupPositions();
292 notifyDataSetChanged(); 314 notifyDataSetChanged();
293 } 315 }
294 316
317 protected ItemGroup createGroup(long timeStamp) {
318 ItemGroup group = new ItemGroup(timeStamp);
319 return group;
320 }
321
295 /** 322 /**
296 * Tells each group where they start in the list. 323 * Tells each group where they start in the list.
297 */ 324 */
298 private void setGroupPositions() { 325 protected void setGroupPositions() {
299 int startIndex = 0; 326 int startIndex = 0;
300 for (ItemGroup group : mGroups) { 327 for (ItemGroup group : mGroups) {
301 group.resetPosition(); 328 group.resetPosition();
302 group.setPosition(startIndex); 329 group.setPosition(startIndex);
303 startIndex += group.size(); 330 startIndex += group.size();
304 } 331 }
305 } 332 }
306 333
307 /** 334 /**
308 * Adds a header as the first group in this adapter. 335 * Adds a header as the first group in this adapter.
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 @Override 428 @Override
402 public final int getItemViewType(int position) { 429 public final int getItemViewType(int position) {
403 Pair<ItemGroup, Integer> pair = getGroupAt(position); 430 Pair<ItemGroup, Integer> pair = getGroupAt(position);
404 if (pair.second == TYPE_HEADER) { 431 if (pair.second == TYPE_HEADER) {
405 return TYPE_HEADER; 432 return TYPE_HEADER;
406 } else if (pair.second == TYPE_FOOTER) { 433 } else if (pair.second == TYPE_FOOTER) {
407 return TYPE_FOOTER; 434 return TYPE_FOOTER;
408 } else if (pair.second == 0) { 435 } else if (pair.second == 0) {
409 return TYPE_DATE; 436 return TYPE_DATE;
410 } else { 437 } else {
411 return TYPE_NORMAL; 438 ItemGroup group = pair.first;
439 return group.getItemViewType(pair.second);
412 } 440 }
413 } 441 }
414 442
415 @Override 443 @Override
416 public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, in t viewType) { 444 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int view Type) {
417 if (viewType == TYPE_DATE) { 445 if (viewType == TYPE_DATE) {
418 return new DateViewHolder(LayoutInflater.from(parent.getContext()).i nflate( 446 return new DateViewHolder(LayoutInflater.from(parent.getContext()).i nflate(
419 getTimedItemViewResId(), parent, false)); 447 getTimedItemViewResId(), parent, false));
420 } else if (viewType == TYPE_NORMAL) { 448 } else if (viewType == TYPE_NORMAL) {
421 return createViewHolder(parent); 449 return createViewHolder(parent);
422 } else if (viewType == TYPE_HEADER) { 450 } else if (viewType == TYPE_HEADER) {
423 return createHeader(parent); 451 return createHeader(parent);
424 } else if (viewType == TYPE_FOOTER) { 452 } else if (viewType == TYPE_FOOTER) {
425 return createFooter(parent); 453 return createFooter(parent);
426 } 454 }
427 assert false; 455 assert false;
428 return null; 456 return null;
429 } 457 }
430 458
431 @Override 459 @Override
432 public final void onBindViewHolder(RecyclerView.ViewHolder holder, int posit ion) { 460 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
433 Pair<Date, TimedItem> pair = getItemAt(position); 461 Pair<Date, TimedItem> pair = getItemAt(position);
434 if (holder instanceof DateViewHolder) { 462 if (holder instanceof DateViewHolder) {
435 ((DateViewHolder) holder).setDate(pair.first); 463 ((DateViewHolder) holder).setDate(pair.first);
436 } else if (!(holder instanceof BasicViewHolder)) { 464 } else if (!(holder instanceof BasicViewHolder)) {
437 bindViewHolderForTimedItem(holder, pair.second); 465 bindViewHolderForTimedItem(holder, pair.second);
438 } 466 }
439 } 467 }
440 468
441 @Override 469 @Override
442 public final int getItemCount() { 470 public final int getItemCount() {
(...skipping 14 matching lines...) Expand all
457 } 485 }
458 486
459 int i = position; 487 int i = position;
460 for (ItemGroup group : mGroups) { 488 for (ItemGroup group : mGroups) {
461 if (i >= group.size()) { 489 if (i >= group.size()) {
462 i -= group.size(); 490 i -= group.size();
463 } else { 491 } else {
464 return new Pair<>(group, i); 492 return new Pair<>(group, i);
465 } 493 }
466 } 494 }
495 System.out.println(
496 ("shakti, position " + position + " groups " + mGroups.size() + " msize " + mSize));
467 assert false; 497 assert false;
468 return null; 498 return null;
469 } 499 }
470 500
471 /** 501 /**
472 * @param item The item to remove from the adapter. 502 * @param item The item to remove from the adapter.
473 */ 503 */
474 protected void removeItem(TimedItem item) { 504 protected void removeItem(TimedItem item) {
475 ItemGroup group = getGroupAt(item.getPosition()).first; 505 ItemGroup group = getGroupAt(item.getPosition()).first;
476 group.removeItem(item); 506 group.removeItem(item);
477 mSize--;
478 507
479 // Remove the group if only the date header is left. 508 // Remove the group if only the date header is left.
480 if (group.size() == 1) { 509 if (group.size() == 1) {
481 mGroups.remove(group); 510 mGroups.remove(group);
482 mSize--;
483 } 511 }
484 512
513 // Somewhat inefficient if number of groups is large.
gone 2017/02/02 23:59:48 Can't you recompute the size based on the item/gro
514 computeItemCount();
485 setGroupPositions(); 515 setGroupPositions();
486 notifyDataSetChanged(); 516 notifyDataSetChanged();
487 } 517 }
488 518
519 protected void computeItemCount() {
520 mSize = 0;
521 for (ItemGroup group : mGroups) {
522 mSize += group.size();
523 }
524 }
525
489 /** 526 /**
490 * Creates a long ID that identifies a particular day in history. 527 * Creates a long ID that identifies a particular day in history.
491 * @param date Date to process. 528 * @param date Date to process.
492 * @return Long that has the day of the year (1-365) in the lowest 16 bits a nd the year in the 529 * @return Long that has the day of the year (1-365) in the lowest 16 bits a nd the year in the
493 * next 16 bits over. 530 * next 16 bits over.
494 */ 531 */
495 private static long getStableIdFromDate(Date date) { 532 private static long getStableIdFromDate(Date date) {
496 Pair<Calendar, Calendar> pair = getCachedCalendars(); 533 Pair<Calendar, Calendar> pair = getCachedCalendars();
497 Calendar calendar = pair.first; 534 Calendar calendar = pair.first;
498 calendar.setTime(date); 535 calendar.setTime(date);
499 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); 536 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
500 long year = calendar.get(Calendar.YEAR); 537 long year = calendar.get(Calendar.YEAR);
501 return (year << 16) + dayOfYear; 538 return (year << 16) + dayOfYear;
502 } 539 }
503 540
504 /** 541 /**
505 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use 542 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use
506 * {@link #compareCalendar(Calendar, Calendar)} instead. 543 * {@link #compareCalendar(Calendar, Calendar)} instead.
507 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise. 544 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise.
508 */ 545 */
509 private static int compareDate(Date date1, Date date2) { 546 protected static int compareDate(Date date1, Date date2) {
510 Pair<Calendar, Calendar> pair = getCachedCalendars(); 547 Pair<Calendar, Calendar> pair = getCachedCalendars();
511 Calendar cal1 = pair.first, cal2 = pair.second; 548 Calendar cal1 = pair.first, cal2 = pair.second;
512 cal1.setTime(date1); 549 cal1.setTime(date1);
513 cal2.setTime(date2); 550 cal2.setTime(date2);
514 return compareCalendar(cal1, cal2); 551 return compareCalendar(cal1, cal2);
515 } 552 }
516 553
517 /** 554 /**
518 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise. 555 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise.
519 */ 556 */
(...skipping 30 matching lines...) Expand all
550 */ 587 */
551 private static AsyncTask<Void, Void, Calendar> createCalendar() { 588 private static AsyncTask<Void, Void, Calendar> createCalendar() {
552 return new AsyncTask<Void, Void, Calendar>() { 589 return new AsyncTask<Void, Void, Calendar>() {
553 @Override 590 @Override
554 protected Calendar doInBackground(Void... unused) { 591 protected Calendar doInBackground(Void... unused) {
555 return Calendar.getInstance(); 592 return Calendar.getInstance();
556 } 593 }
557 }.execute(); 594 }.execute();
558 } 595 }
559 } 596 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698