diff options
8 files changed, 154 insertions, 212 deletions
diff --git a/res/layout/call_log_fragment.xml b/res/layout/call_log_fragment.xml index 74c630959..c126b778b 100644 --- a/res/layout/call_log_fragment.xml +++ b/res/layout/call_log_fragment.xml @@ -61,18 +61,11 @@ <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> - <!-- clipChildren=false is required to ensure shadows drawn - within list items aren't clipped by the list item bounds. --> - <ListView android:id="@android:id/list" + + <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:fadingEdge="none" - android:scrollbarStyle="outsideOverlay" - android:background="@color/background_dialer_list_items" - android:divider="@null" - android:nestedScrollingEnabled="true" - android:clipChildren="false" - /> + android:background="@color/background_dialer_list_items" /> <include android:id="@+id/empty_list_view" diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index fd6b37b8c..5d5145fe4 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -23,6 +23,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.PhoneLookup; +import android.support.v7.widget.RecyclerView.ViewHolder; import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberUtils; import android.text.TextUtils; @@ -225,13 +226,12 @@ public class CallLogAdapter extends GroupingListAdapter mLoading = loading; } - @Override public boolean isEmpty() { if (mLoading) { // We don't want the empty state to show when loading. return false; } else { - return super.isEmpty(); + return getItemCount() == 0; } } @@ -262,48 +262,19 @@ public class CallLogAdapter extends GroupingListAdapter } @Override - protected View newStandAloneView(Context context, ViewGroup parent) { - return newChildView(context, parent); - } - - @Override - protected View newGroupView(Context context, ViewGroup parent) { - return newChildView(context, parent); - } - - @Override - protected View newChildView(Context context, ViewGroup parent) { - LayoutInflater inflater = LayoutInflater.from(context); + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.call_log_list_item, parent, false); // Get the views to bind to and cache them. - CallLogListItemViews views = CallLogListItemViews.fromView(context, view); + CallLogListItemViews views = CallLogListItemViews.fromView(mContext, view); view.setTag(views); // Set text height to false on the TextViews so they don't have extra padding. views.phoneCallDetailsViews.nameView.setElegantTextHeight(false); views.phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false); - return view; - } - - @Override - protected void bindStandAloneView(View view, Context context, Cursor cursor) { - bindView(view, cursor, 1); - } - - @Override - protected void bindChildView(View view, Context context, Cursor cursor) { - bindView(view, cursor, 1); - } - - @Override - protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize, - boolean expanded) { - bindView(view, cursor, groupSize); - } - - private void findAndCacheViews(View view) { + return (CallLogListItemViews) view.getTag(); } /** @@ -312,12 +283,17 @@ public class CallLogAdapter extends GroupingListAdapter * should not. It invokes cross-process methods and the repeat execution can get costly. * * @param callLogItemView the view corresponding to this entry - * @param c the cursor pointing to the entry in the call log * @param count the number of entries in the current item, greater than 1 if it is a group */ - public void bindView(View callLogItemView, Cursor c, int count) { - callLogItemView.setAccessibilityDelegate(mAccessibilityDelegate); - final CallLogListItemViews views = (CallLogListItemViews) callLogItemView.getTag(); + public void onBindViewHolder(ViewHolder viewHolder, int position) { + Cursor c = (Cursor) getItem(position); + if (c == null) { + return; + } + int count = getGroupSize(position); + + CallLogListItemViews views = (CallLogListItemViews) viewHolder; + views.rootView.setAccessibilityDelegate(mAccessibilityDelegate); // Default case: an item in the call log. views.primaryActionView.setVisibility(View.VISIBLE); @@ -435,7 +411,7 @@ public class CallLogAdapter extends GroupingListAdapter // Listen for the first draw if (mViewTreeObserver == null) { - mViewTreeObserver = callLogItemView.getViewTreeObserver(); + mViewTreeObserver = views.rootView.getViewTreeObserver(); mViewTreeObserver.addOnPreDrawListener(this); } } diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java index d69c2ed7e..4f4fc1b94 100644 --- a/src/com/android/dialer/calllog/CallLogFragment.java +++ b/src/com/android/dialer/calllog/CallLogFragment.java @@ -21,8 +21,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.Activity; import android.app.DialogFragment; +import android.app.Fragment; import android.app.KeyguardManager; -import android.app.ListFragment; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; @@ -34,10 +34,11 @@ import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract; import android.provider.VoicemailContract.Status; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.LinearLayoutManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.ListView; @@ -60,7 +61,7 @@ import java.util.List; * Displays a list of call log entries. To filter for a particular kind of call * (all, missed or voicemails), specify it in the constructor. */ -public class CallLogFragment extends ListFragment +public class CallLogFragment extends Fragment implements CallLogQueryHandler.Listener, CallLogAdapter.OnReportButtonClickListener, CallLogAdapter.CallFetcher { private static final String TAG = "CallLogFragment"; @@ -76,6 +77,8 @@ public class CallLogFragment extends ListFragment private static final String KEY_LOG_LIMIT = "log_limit"; private static final String KEY_DATE_LIMIT = "date_limit"; + private RecyclerView mRecyclerView; + private LinearLayoutManager mLayoutManager; private CallLogAdapter mAdapter; private CallLogQueryHandler mCallLogQueryHandler; private boolean mScrollToTop; @@ -172,9 +175,6 @@ public class CallLogFragment extends ListFragment } String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); - mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, - new ContactInfoHelper(getActivity(), currentCountryIso), this); - setListAdapter(mAdapter); mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), this, mLogLimit); mKeyguardManager = @@ -201,9 +201,8 @@ public class CallLogFragment extends ListFragment // This will update the state of the "Clear call log" menu item. getActivity().invalidateOptionsMenu(); - final ListView listView = getListView(); boolean showListView = cursor.getCount() > 0; - listView.setVisibility(showListView ? View.VISIBLE : View.GONE); + mRecyclerView.setVisibility(showListView ? View.VISIBLE : View.GONE); mEmptyListView.setVisibility(!showListView ? View.VISIBLE : View.GONE); if (mScrollToTop) { @@ -213,8 +212,9 @@ public class CallLogFragment extends ListFragment // will not experience the illusion of downward motion. Instead, // if we're not already near the top of the list, we instantly jump // near the top, and animate from there. - if (listView.getFirstVisiblePosition() > 5) { - listView.setSelection(5); + if (mLayoutManager.findFirstVisibleItemPosition() > 5) { + // TODO: Jump to near the top, then begin smooth scroll. + mRecyclerView.smoothScrollToPosition(0); } // Workaround for framework issue: the smooth-scroll doesn't // occur if setSelection() is called immediately before. @@ -224,7 +224,7 @@ public class CallLogFragment extends ListFragment if (getActivity() == null || getActivity().isFinishing()) { return; } - listView.smoothScrollToPosition(0); + mRecyclerView.smoothScrollToPosition(0); } }); @@ -269,6 +269,17 @@ public class CallLogFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { View view = inflater.inflate(R.layout.call_log_fragment, container, false); + + mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); + mRecyclerView.setHasFixedSize(true); + mLayoutManager = new LinearLayoutManager(getActivity()); + mRecyclerView.setLayoutManager(mLayoutManager); + + String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); + mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, + new ContactInfoHelper(getActivity(), currentCountryIso), this); + mRecyclerView.setAdapter(mAdapter); + mVoicemailStatusHelper = new VoicemailStatusHelperImpl(); mStatusMessageView = view.findViewById(R.id.voicemail_status); mStatusMessageText = (TextView) view.findViewById(R.id.voicemail_status_message); @@ -280,7 +291,6 @@ public class CallLogFragment extends ListFragment public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mEmptyListView = view.findViewById(R.id.empty_list_view); - getListView().setItemsCanFocus(true); updateEmptyMessage(mCallTypeFilter); } diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java index 9d11a3ab6..f2bed531f 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViews.java +++ b/src/com/android/dialer/calllog/CallLogListItemViews.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.net.Uri; import android.provider.CallLog.Calls; +import android.support.v7.widget.RecyclerView; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import android.view.View; @@ -44,7 +45,7 @@ import com.android.dialer.R; * is a way of isolating view logic from the CallLogAdapter. We should consider moving that logic * if the call log list item is eventually represented as a UI component. */ -public final class CallLogListItemViews { +public final class CallLogListItemViews extends RecyclerView.ViewHolder { /** The root view of the call log list item */ public final View rootView; /** The quick contact badge for the contact. */ @@ -147,6 +148,7 @@ public final class CallLogListItemViews { PhoneCallDetailsViews phoneCallDetailsViews, View callLogEntryView, TextView dayGroupHeader) { + super(rootView); mContext = context; this.rootView = rootView; diff --git a/src/com/android/dialer/calllog/GroupingListAdapter.java b/src/com/android/dialer/calllog/GroupingListAdapter.java index 78955492e..501e88df0 100644 --- a/src/com/android/dialer/calllog/GroupingListAdapter.java +++ b/src/com/android/dialer/calllog/GroupingListAdapter.java @@ -21,6 +21,8 @@ import android.database.ContentObserver; import android.database.Cursor; import android.database.DataSetObserver; import android.os.Handler; +import android.support.v7.widget.RecyclerView; +import android.util.Log; import android.util.SparseIntArray; import android.view.View; import android.view.ViewGroup; @@ -34,7 +36,7 @@ import com.android.contacts.common.testing.NeededForTesting; * The list has three types of elements: stand-alone, group header and group child. Groups are * collapsible and collapsed by default. This is used by the call log to group related entries. */ -abstract class GroupingListAdapter extends BaseAdapter { +abstract class GroupingListAdapter extends RecyclerView.Adapter { private static final int GROUP_METADATA_ARRAY_INITIAL_SIZE = 16; private static final int GROUP_METADATA_ARRAY_INCREMENT = 128; @@ -109,11 +111,6 @@ abstract class GroupingListAdapter extends BaseAdapter { public void onChanged() { notifyDataSetChanged(); } - - @Override - public void onInvalidated() { - notifyDataSetInvalidated(); - } }; public GroupingListAdapter(Context context) { @@ -127,15 +124,7 @@ abstract class GroupingListAdapter extends BaseAdapter { */ protected abstract void addGroups(Cursor cursor); - protected abstract View newStandAloneView(Context context, ViewGroup parent); - protected abstract void bindStandAloneView(View view, Context context, Cursor cursor); - - protected abstract View newGroupView(Context context, ViewGroup parent); - protected abstract void bindGroupView(View view, Context context, Cursor cursor, int groupSize, - boolean expanded); - - protected abstract View newChildView(Context context, ViewGroup parent); - protected abstract void bindChildView(View view, Context context, Cursor cursor); + protected abstract void onContentChanged(); /** * Cache should be reset whenever the cursor changes or groups are expanded or collapsed. @@ -149,9 +138,6 @@ abstract class GroupingListAdapter extends BaseAdapter { mPositionCache.clear(); } - protected void onContentChanged() { - } - public void changeCursor(Cursor cursor) { if (cursor == mCursor) { return; @@ -171,13 +157,10 @@ abstract class GroupingListAdapter extends BaseAdapter { cursor.registerDataSetObserver(mDataSetObserver); mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id"); notifyDataSetChanged(); - } else { - // notify the observers about the lack of a data set - notifyDataSetInvalidated(); } - } + @NeededForTesting public Cursor getCursor() { return mCursor; } @@ -231,7 +214,8 @@ abstract class GroupingListAdapter extends BaseAdapter { return need; } - public int getCount() { + @Override + public int getItemCount() { if (mCursor == null) { return 0; } @@ -343,6 +327,7 @@ abstract class GroupingListAdapter extends BaseAdapter { if (position < listPosition) { metadata.itemType = ITEM_TYPE_STANDALONE; metadata.cursorPosition = cursorPosition - (listPosition - position); + metadata.childCount = 1; return; } @@ -382,6 +367,7 @@ abstract class GroupingListAdapter extends BaseAdapter { // The required item is past the last group metadata.itemType = ITEM_TYPE_STANDALONE; metadata.cursorPosition = cursorPosition + (position - listPosition); + metadata.childCount = 1; } /** @@ -421,12 +407,6 @@ abstract class GroupingListAdapter extends BaseAdapter { notifyDataSetChanged(); } - @Override - public int getViewTypeCount() { - return 3; - } - - @Override public int getItemViewType(int position) { obtainPositionMetadata(mPositionMetadata, position); return mPositionMetadata.itemType; @@ -454,37 +434,16 @@ abstract class GroupingListAdapter extends BaseAdapter { } } - public View getView(int position, View convertView, ViewGroup parent) { - obtainPositionMetadata(mPositionMetadata, position); - View view = convertView; - if (view == null) { - switch (mPositionMetadata.itemType) { - case ITEM_TYPE_STANDALONE: - view = newStandAloneView(mContext, parent); - break; - case ITEM_TYPE_GROUP_HEADER: - view = newGroupView(mContext, parent); - break; - case ITEM_TYPE_IN_GROUP: - view = newChildView(mContext, parent); - break; - } - } - - mCursor.moveToPosition(mPositionMetadata.cursorPosition); - switch (mPositionMetadata.itemType) { - case ITEM_TYPE_STANDALONE: - bindStandAloneView(view, mContext, mCursor); - break; - case ITEM_TYPE_GROUP_HEADER: - bindGroupView(view, mContext, mCursor, mPositionMetadata.childCount, - mPositionMetadata.isExpanded); - break; - case ITEM_TYPE_IN_GROUP: - bindChildView(view, mContext, mCursor); - break; - + /** + * Used for setting the cursor without triggering a UI thread update. + */ + @NeededForTesting + public void setCursorForTesting(Cursor cursor) { + if (cursor != null) { + mCursor = cursor; + cursor.registerContentObserver(mChangeObserver); + cursor.registerDataSetObserver(mDataSetObserver); + mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id"); } - return view; } } diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java index 845e279c9..bffbe5cf5 100644 --- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java +++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java @@ -87,7 +87,8 @@ public class CallLogAdapterTest extends AndroidTestCase { mCursor.addRow(createCallLogEntry()); // Bind the views of a single row. - mAdapter.bindStandAloneView(mView, getContext(), mCursor); + mAdapter.changeCursor(mCursor); + mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0); // There is one request for contact details. assertEquals(1, mAdapter.getContactInfoCache().requests.size()); @@ -105,7 +106,8 @@ public class CallLogAdapterTest extends AndroidTestCase { mCursor.addRow(createCallLogEntryWithCachedValues()); // Bind the views of a single row. - mAdapter.bindStandAloneView(mView, getContext(), mCursor); + mAdapter.changeCursor(mCursor); + mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0); // There is one request for contact details. assertEquals(1, mAdapter.getContactInfoCache().requests.size()); @@ -123,7 +125,9 @@ public class CallLogAdapterTest extends AndroidTestCase { mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. - mAdapter.bindStandAloneView(mView, getContext(), mCursor); + mAdapter.changeCursor(mCursor); + mAdapter.onBindViewHolder( + CallLogListItemViews.fromView(getContext(), mView), 0); // There is one request for contact details. assertEquals(1, mAdapter.getContactInfoCache().requests.size()); @@ -138,7 +142,8 @@ public class CallLogAdapterTest extends AndroidTestCase { mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, createContactInfo()); // Bind the views of a single row. - mAdapter.bindStandAloneView(mView, getContext(), mCursor); + mAdapter.changeCursor(mCursor); + mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0); // Cache and call log are up-to-date: no need to request update. assertEquals(0, mAdapter.getContactInfoCache().requests.size()); @@ -153,7 +158,8 @@ public class CallLogAdapterTest extends AndroidTestCase { mAdapter.injectContactInfoForTest(TEST_NUMBER, TEST_COUNTRY_ISO, info); // Bind the views of a single row. - mAdapter.bindStandAloneView(mView, getContext(), mCursor); + mAdapter.changeCursor(mCursor); + mAdapter.onBindViewHolder(CallLogListItemViews.fromView(getContext(), mView), 0); // There is one request for contact details. assertEquals(1, mAdapter.getContactInfoCache().requests.size()); diff --git a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java index b57489d55..fe14f8709 100644 --- a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java +++ b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java @@ -30,6 +30,7 @@ import android.net.Uri; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.VoicemailContract; +import android.support.v7.widget.RecyclerView.ViewHolder; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.test.ActivityInstrumentationTestCase2; @@ -94,9 +95,9 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme // An item in the call list. All the methods performing checks use it. private CallLogListItemViews mItem; - // The list of views representing the data in the DB. View are in - // reverse order compare to the DB. - private View[] mList; + + // The list of view holderss representing the data in the DB, in reverse order from the DB. + private ViewHolder[] mList; public CallLogFragmentTest() { super(FragmentTestActivity.class); @@ -129,6 +130,7 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme mAdapter.pauseCache(); mParentView = new FrameLayout(mActivity); mCursor = new MatrixCursor(CallLogQuery._PROJECTION); + mAdapter.setCursorForTesting(mCursor); } /** @@ -140,7 +142,7 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme @MediumTest public void testCallViewIsNotVisibleForPrivateAndUnknownNumbers() { final int SIZE = 100; - mList = new View[SIZE]; + mList = new ViewHolder[SIZE]; // Insert the first batch of entries. mCursor.moveToFirst(); @@ -168,34 +170,34 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme insertPrivate(NOW, 0); insertPrivate(NOW, 0); insertPrivate(NOW, 0); - View view = mAdapter.newGroupView(getActivity(), mParentView); - mAdapter.bindGroupView(view, getActivity(), mCursor, 3, false); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + mAdapter.onBindViewHolder(viewHolder, /* position */ 0); } @MediumTest public void testCallAndGroupViews_StandAloneView() { mCursor.moveToFirst(); insertPrivate(NOW, 0); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, 0); + bindViewForTest(viewHolder); } @MediumTest public void testCallAndGroupViews_ChildView() { mCursor.moveToFirst(); insertPrivate(NOW, 0); - View view = mAdapter.newChildView(getActivity(), mParentView); - mAdapter.bindChildView(view, getActivity(), mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + mAdapter.onBindViewHolder(viewHolder, /* position */ 0); } @MediumTest public void testBindView_NumberOnlyNoCache() { mCursor.moveToFirst(); insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, TEST_NUMBER); } @@ -206,10 +208,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE); values[CallLogQuery.CACHED_FORMATTED_NUMBER] = TEST_FORMATTED_NUMBER; insertValues(values); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, TEST_FORMATTED_NUMBER); } @@ -220,10 +222,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme // {@value com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL} insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, "John Doe"); assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME)); } @@ -233,10 +235,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme mCursor.moveToFirst(); insertWithCachedValues("sip:johndoe@gmail.com", NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, "John Doe"); assertLabel(views, "sip:johndoe@gmail.com", "sip:johndoe@gmail.com"); } @@ -248,10 +250,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme // {@value com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL} insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_HOME, TEST_DEFAULT_CUSTOM_LABEL); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, "John Doe"); assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME)); } @@ -263,10 +265,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme // {@link com.android.dialer.calllog.ContactInfo#GEOCODE_AS_LABEL} insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_WORK, TEST_DEFAULT_CUSTOM_LABEL); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, "John Doe"); assertLabel(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_WORK)); } @@ -277,10 +279,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme String numberLabel = "My label"; insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_CUSTOM, numberLabel); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertNameIs(views, "John Doe"); assertLabel(views, TEST_FORMATTED_NUMBER, numberLabel); } @@ -290,10 +292,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme mCursor.moveToFirst(); insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE, "John Doe", Phone.TYPE_HOME, ""); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertTrue(views.quickContactView.isEnabled()); } @@ -301,10 +303,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme public void testBindView_WithoutQuickContactBadge() { mCursor.moveToFirst(); insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; assertFalse(views.quickContactView.isEnabled()); } @@ -312,10 +314,11 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme public void testBindView_CallButton() { mCursor.moveToFirst(); insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + mAdapter.changeCursor(mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; // The primaryActionView tag is set in the // {@link com.android.dialer.calllog.CallLogAdapter#bindView} method. If it is possible @@ -333,10 +336,10 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme public void testBindView_PlayButton() { mCursor.moveToFirst(); insertVoicemail(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0); - View view = mAdapter.newStandAloneView(getActivity(), mParentView); - bindViewForTest(view, mCursor); + ViewHolder viewHolder = mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0); + bindViewForTest(viewHolder); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); + CallLogListItemViews views = (CallLogListItemViews) viewHolder; IntentProvider intentProvider = (IntentProvider) views.voicemailButtonView.getTag(); Intent intent = intentProvider.getIntent(mActivity); // Starts the call detail activity. @@ -372,7 +375,7 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme if (null == mList[i]) { break; } - mItem = (CallLogListItemViews) mList[i].getTag(); + mItem = (CallLogListItemViews) mList[i]; int presentation = getPhoneNumberPresentationForListEntry(i); if (presentation == Calls.PRESENTATION_RESTRICTED || presentation == Calls.PRESENTATION_UNKNOWN) { @@ -420,11 +423,12 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme private void buildViewListFromDb() { int i = 0; mCursor.moveToLast(); - while(!mCursor.isBeforeFirst()) { + while (!mCursor.isBeforeFirst()) { if (null == mList[i]) { - mList[i] = mAdapter.newStandAloneView(mActivity, mParentView); + mList[i] = mAdapter.onCreateViewHolder(mParentView, /* itemType */ 0); } - bindViewForTest(mList[i], mCursor); + // Bind to the proper position, despite iterating in reverse. + bindViewForTest(mList[i], mCursor.getCount() - i - 1); mCursor.moveToPrevious(); i++; } @@ -446,12 +450,15 @@ public class CallLogFragmentTest extends ActivityInstrumentationTestCase2<Fragme * unit tests can access the buttons contained within. * * @param view The current call log row. - * @param cursor The cursor to bind from. + * @param position The position of hte item. */ - private void bindViewForTest(View view, MatrixCursor cursor) { - mAdapter.bindView(view, cursor, /* count */ 1); - CallLogListItemViews views = (CallLogListItemViews) view.getTag(); - mAdapter.expandItem(views, /* expand */ true); + private void bindViewForTest(ViewHolder viewHolder, int position) { + mAdapter.onBindViewHolder(viewHolder, position); + mAdapter.expandItem((CallLogListItemViews) viewHolder, /* expand */ true); + } + + private void bindViewForTest(ViewHolder viewHolder) { + bindViewForTest(viewHolder, /* position */ 0); } /** diff --git a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java index 3eb5f06b1..53583e0a7 100644 --- a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java +++ b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java @@ -23,6 +23,7 @@ import static com.android.dialer.calllog.GroupingListAdapter.ITEM_TYPE_STANDALON import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; +import android.support.v7.widget.RecyclerView; import android.test.AndroidTestCase; import android.text.TextUtils; import android.view.View; @@ -34,7 +35,7 @@ import android.view.ViewGroup; * Running all tests: * * adb shell am instrument -e class com.android.dialer.calllog.GroupingListAdapterTests \ - * -w com.google.android.dialer.tests/android.test.InstrumentationTestRunner + * -w com.android.dialer.tests/android.test.InstrumentationTestRunner */ public class GroupingListAdapterTests extends AndroidTestCase { @@ -76,34 +77,22 @@ public class GroupingListAdapterTests extends AndroidTestCase { } @Override - protected void bindChildView(View view, Context context, Cursor cursor) { + public void onContentChanged() { + // Do nothing. } @Override - protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize, - boolean expanded) { - } - - @Override - protected void bindStandAloneView(View view, Context context, Cursor cursor) { - } - - @Override - protected View newChildView(Context context, ViewGroup parent) { + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) { return null; } @Override - protected View newGroupView(Context context, ViewGroup parent) { - return null; - } - - @Override - protected View newStandAloneView(Context context, ViewGroup parent) { - return null; + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { + // Do nothing. } }; + private void buildCursor(String... numbers) { mCursor = new MatrixCursor(PROJECTION); mNextId = 1; @@ -117,7 +106,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor("1", "2", "3"); mAdapter.changeCursor(mCursor); - assertEquals(3, mAdapter.getCount()); + assertEquals(3, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1); assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 2); @@ -127,7 +116,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor("1", "1", "2"); mAdapter.changeCursor(mCursor); - assertEquals(2, mAdapter.getCount()); + assertEquals(2, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0); assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2); } @@ -137,7 +126,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { mAdapter.changeCursor(mCursor); mAdapter.toggleGroup(0); - assertEquals(4, mAdapter.getCount()); + assertEquals(4, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, true, 0); assertPositionMetadata(1, ITEM_TYPE_IN_GROUP, false, 0); assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1); @@ -150,7 +139,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { mAdapter.toggleGroup(0); mAdapter.toggleGroup(0); - assertEquals(2, mAdapter.getCount()); + assertEquals(2, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0); assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2); } @@ -159,7 +148,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor("1", "2", "2", "2", "3"); mAdapter.changeCursor(mCursor); - assertEquals(3, mAdapter.getCount()); + assertEquals(3, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1); assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 4); @@ -170,7 +159,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { mAdapter.changeCursor(mCursor); mAdapter.toggleGroup(1); - assertEquals(6, mAdapter.getCount()); + assertEquals(6, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1); assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1); @@ -183,7 +172,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor("1", "2", "3", "3", "3"); mAdapter.changeCursor(mCursor); - assertEquals(3, mAdapter.getCount()); + assertEquals(3, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1); assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, false, 2); @@ -194,7 +183,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { mAdapter.changeCursor(mCursor); mAdapter.toggleGroup(2); - assertEquals(6, mAdapter.getCount()); + assertEquals(6, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1); assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, true, 2); @@ -207,7 +196,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor("1", "2", "2", "3", "4", "4", "5", "5", "6"); mAdapter.changeCursor(mCursor); - assertEquals(6, mAdapter.getCount()); + assertEquals(6, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1); assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3); @@ -225,7 +214,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { // 4th to the 6th position mAdapter.toggleGroup(6); - assertEquals(10, mAdapter.getCount()); + assertEquals(10, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1); assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1); @@ -243,7 +232,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { mAdapter.changeCursor(mCursor); // First pass - building up cache - assertEquals(6, mAdapter.getCount()); + assertEquals(6, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1); assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3); @@ -252,7 +241,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 8); // Second pass - using cache - assertEquals(6, mAdapter.getCount()); + assertEquals(6, mAdapter.getItemCount()); assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0); assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1); assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3); @@ -295,7 +284,7 @@ public class GroupingListAdapterTests extends AndroidTestCase { buildCursor(numbers); mAdapter.changeCursor(mCursor); - assertEquals(250, mAdapter.getCount()); + assertEquals(250, mAdapter.getItemCount()); } private void assertPositionMetadata(int position, int itemType, boolean isExpanded, |