1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts.editor; 18 19 import android.os.Bundle; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import com.android.contacts.model.RawContactDelta; 24 import com.android.contacts.model.ValuesDelta; 25 import com.android.contacts.model.dataitem.DataKind; 26 27 /** 28 * A class that provides unique view ids for {@link ContentEditorView}, 29 * {@link LabeledEditorView} and {@link EditView} on {@link EditContactActivity}. 30 * It is used to assign a unique but consistent id to each view across {@link EditContactActivity}'s 31 * lifecycle, so that we can re-construct view state (e.g. focused view) when the screen rotates. 32 * 33 * <p>This class is not thread safe. 34 */ 35 public final class ViewIdGenerator implements Parcelable { 36 private static final int INVALID_VIEW_ID = 0; 37 private static final int INITIAL_VIEW_ID = 1; 38 39 public static final int NO_VIEW_INDEX = -1; 40 41 private int mNextId; 42 43 /** 44 * Used as a map from the "key" of the views to actual ids. {@link #getId()} generates keys for 45 * the views. 46 */ 47 private Bundle mIdMap = new Bundle(); 48 49 private static final char KEY_SEPARATOR = '*'; 50 51 private final static StringBuilder sWorkStringBuilder = new StringBuilder(); 52 ViewIdGenerator()53 public ViewIdGenerator() { 54 mNextId = INITIAL_VIEW_ID; 55 } 56 57 /** {@inheritDoc} */ describeContents()58 public int describeContents() { 59 return 0; 60 } 61 62 /** 63 * Returns an id for a view associated with specified contact field. 64 * 65 * @param entity {@link RawContactDelta} associated with the view 66 * @param kind {@link DataKind} associated with the view, or null if none exists. 67 * @param values {@link ValuesDelta} associated with the view, or null if none exists. 68 * @param viewIndex index of the view in the parent {@link Editor}, if it's a leave view. 69 * Otherwise, pass {@link #NO_VIEW_INDEX}. 70 */ getId(RawContactDelta entity, DataKind kind, ValuesDelta values, int viewIndex)71 public int getId(RawContactDelta entity, DataKind kind, ValuesDelta values, 72 int viewIndex) { 73 final String k = getMapKey(entity, kind, values, viewIndex); 74 75 int id = mIdMap.getInt(k, INVALID_VIEW_ID); 76 if (id == INVALID_VIEW_ID) { 77 // Make sure the new id won't conflict with auto-generated ids by masking with 0xffff. 78 id = (mNextId++) & 0xFFFF; 79 mIdMap.putInt(k, id); 80 } 81 return id; 82 } 83 getMapKey(RawContactDelta entity, DataKind kind, ValuesDelta values, int viewIndex)84 private static String getMapKey(RawContactDelta entity, DataKind kind, ValuesDelta values, 85 int viewIndex) { 86 sWorkStringBuilder.setLength(0); 87 if (entity != null) { 88 sWorkStringBuilder.append(entity.getValues().getId()); 89 90 if (kind != null) { 91 sWorkStringBuilder.append(KEY_SEPARATOR); 92 sWorkStringBuilder.append(kind.mimeType); 93 94 if (values != null) { 95 sWorkStringBuilder.append(KEY_SEPARATOR); 96 sWorkStringBuilder.append(values.getId()); 97 98 if (viewIndex != NO_VIEW_INDEX) { 99 sWorkStringBuilder.append(KEY_SEPARATOR); 100 sWorkStringBuilder.append(viewIndex); 101 } 102 } 103 } 104 } 105 return sWorkStringBuilder.toString(); 106 } 107 108 /** {@Override} */ writeToParcel(Parcel dest, int flags)109 public void writeToParcel(Parcel dest, int flags) { 110 dest.writeInt(mNextId); 111 dest.writeBundle(mIdMap); 112 } 113 readFromParcel(Parcel src)114 private void readFromParcel(Parcel src) { 115 mNextId = src.readInt(); 116 mIdMap = src.readBundle(); 117 } 118 119 public static final Parcelable.Creator<ViewIdGenerator> CREATOR = 120 new Parcelable.Creator<ViewIdGenerator>() { 121 public ViewIdGenerator createFromParcel(Parcel in) { 122 final ViewIdGenerator vig = new ViewIdGenerator(); 123 vig.readFromParcel(in); 124 return vig; 125 } 126 127 public ViewIdGenerator[] newArray(int size) { 128 return new ViewIdGenerator[size]; 129 } 130 }; 131 } 132