Какова основная цель setTag() getTag() методов View?
Какова основная цель таких методов как setTag()
а также getTag()
из View
типа объектов?
Правильно ли я считаю, что могу связать любое количество объектов с одним представлением?
8 ответов
Допустим, вы генерируете несколько похожих взглядов. Вы могли бы установить OnClickListener
для каждого вида индивидуально:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
Тогда вы должны создать уникальный onClick
метод для каждого представления, даже если они делают похожие вещи, например:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
Это потому что onClick
имеет только один параметр, View
и он должен получать другую информацию из переменных экземпляра или конечных локальных переменных во вложенных областях. Что мы действительно хотим, так это получить информацию от самих мнений.
Войти getTag
/setTag
:
button1.setTag(1);
button2.setTag(2);
Теперь мы можем использовать один и тот же OnClickListener для каждой кнопки:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
Это в основном способ для представлений иметь воспоминания.
Я хотел бы добавить несколько слов.
Хотя с помощью get/setTag(Object)
кажется очень полезным в конкретном случае шаблона ViewHolder, я бы рекомендовал подумать дважды, прежде чем использовать его в других случаях. Почти всегда есть другое хорошее дизайнерское решение.
Основная причина в том, что код перестает поддерживаться довольно быстро.
Для других разработчиков не очевидно, что вы разработали для хранения в качестве тега. Методы setTag / getTag не являются описательными.
Он хранит только
Object
так что требует литья, когда вы хотитеgetTag
, Вы можете получить неожиданный сбой позже, когда решите изменить тип хранимого объекта в теге.Это история из реальной жизни. У нас был довольно большой проект с множеством адаптеров, асинхронными операциями с представлениями и так далее. Один разработчик решил
set/getTag
в его части кода, но другой уже установил тег для этого представления. В конце концов, кто-то не смог найти свой собственный тег и был очень смущен. Это стоило нам нескольких часов, чтобы найти ошибку.
setTag(int key, Object tag)
выглядит намного лучше, потому что вы можете генерировать уникальные ключи для каждого тега (используя ресурсы id), но есть существенное ограничение для Android < 4.0. Из документов Lint:
До Android 4.0 реализация View.setTag(int, Object) сохраняла объекты в статической карте, где на значения были жесткие ссылки. Это означает, что если объект содержит какие-либо ссылки, указывающие на контекст, контекст (который указывает практически на все остальное) будет утечкой. Если вы передаете представление, представление предоставляет ссылку на контекст, который его создал. Точно так же держатели вида обычно содержат вид, и курсоры иногда также связаны с представлениями.
Мы можем использовать setTag()
а также getTag()
установить и получить пользовательские объекты в соответствии с нашим требованием. setTag()
метод принимает аргумент типа Object
, а также getTag()
возвращает Object
,
Например,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Это очень полезно для пользовательских ArrayAdapter
с помощью. Это какая-то оптимизация. Там setTag
используется как ссылка на объект, который ссылается на некоторые части макета (которые отображаются в ListView
) вместо findViewById
,
static class ViewHolder {
TextView tvPost;
TextView tvDate;
ImageView thumb;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.postitem, null);
ViewHolder vh = new ViewHolder();
vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
convertView.setTag(vh);
}
....................
}
Установка тегов действительно полезна, когда у вас есть ListView и вы хотите перерабатывать / повторно использовать представления. Таким образом, ListView становится очень похожим на более новый RecyclerView.
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}
В отличие от идентификаторов, теги не используются для идентификации представлений. По сути, теги - это дополнительная часть информации, которая может быть связана с представлением. Чаще всего они используются для удобства хранения данных, связанных с представлениями, в самих представлениях, а не для помещения их в отдельную структуру.
Ссылка: http://developer.android.com/reference/android/view/View.html
Код был добавлен, и изображение было добавлено в базу данных. Я не смог запросить его или показать из базы данных. Вы можете помочь. Спасибо
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
open_btn = (Button) findViewById(R.id.open);
save_btn = (Button) findViewById(R.id.save);
open_Img = (ImageView) findViewById(R.id.openImage);
saveImg = (ImageView) findViewById(R.id.saveImage);
}
public void save(View view) {
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, 100);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == RESULT_OK) {
Uri uri = data.getData();
saveImg.setImageURI(uri);
bitmap = ((BitmapDrawable)saveImg.getDrawable()).getBitmap();
byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,100,byteArrayOutputStream);
encodeImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(),Base64.DEFAULT);
}
}
public void open(View view) {
byte[] bytes =Base64.decode(encodeImage,Base64.DEFAULT);
Bitmap decodBitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
open_Img.setImageBitmap(decodBitmap);
}