Java 对getTag()感到困惑
我刚刚开始学习Java和编程。我在这里学习了一个教程: 但现在我已经被困了几个小时!!!请帮忙 它工作得很好,我还通过使用ViewHolder模式优化了ListView,这是一个额外的挑战Java 对getTag()感到困惑,java,android,listview,Java,Android,Listview,我刚刚开始学习Java和编程。我在这里学习了一个教程: 但现在我已经被困了几个小时!!!请帮忙 它工作得很好,我还通过使用ViewHolder模式优化了ListView,这是一个额外的挑战 public class SongAdapter extends BaseAdapter { private ArrayList<Song> songs; private LayoutInflater songInf; public SongAdapter(Contex
public class SongAdapter extends BaseAdapter {
private ArrayList<Song> songs;
private LayoutInflater songInf;
public SongAdapter(Context c, ArrayList<Song> theSongs) {
songs = theSongs;
songInf = LayoutInflater.from(c);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return songs.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
class ViewHolder{
TextView songView;
TextView artistView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LinearLayout songLay = (LinearLayout)convertView;
if (songLay == null) {
songLay = (LinearLayout) songInf.inflate
(R.layout.song, parent, false);
//get view holder instance
holder = new ViewHolder();
//populate viewholder with artist and text views
holder.songView = (TextView) songLay.findViewById(R.id.song_title);
holder.artistView = (TextView) songLay.findViewById(R.id.song_artist);
songLay.setTag(R.string.TAG1,holder);
}
else {
holder = (ViewHolder) songLay.getTag(R.string.TAG1);
}
//get song using position
Song currSong = songs.get(position);
//get title and artist strings
holder.songView.setText(currSong.getSongTitle());
holder.artistView.setText(currSong.getArtist());
return songLay;
}
}
这是MusicService.java中的相关代码
public void setSong(int songIndex){
songPosn = songIndex;
}
public void playSong(){
//play a song
player.reset();
//get song
MainActivity.Song playSong = songs.get(songPosn);
//get ID
long currSong = playSong.getID();
//set uri
Uri trackUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,currSong);
try{
player.setDataSource(getApplicationContext(), trackUri);
}
catch(Exception e){
Log.e("MUSIC SERVICE", "Error setting data source", e);
}
player.prepareAsync();
}
我得到一个例外:
03-15 01:49:21.065 14179-14179/com.example.mediaplayertut E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3838)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at android.view.View$1.onClick(View.java:3833)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.mediaplayertut.MainActivity.songPicked(MainActivity.java:152)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at android.view.View$1.onClick(View.java:3833)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
我曾经发现自己想要使用标记属性作为视图的一种方便方法。从那以后,我决定,如果您使用标记属性作为一种方便的方法,那么您没有做错,但是通常有一种更优雅的解决方法 在您的例子中,我将使用静态视图数组,并引用数组中视图的索引来访问该视图的索引。如果您使用
适配器使用ListView
或其衍生产品,那么使用ArrayAdapter
就更容易了,而且使用ArrayAdapter
几乎是可笑的简单,因为视图是为您存储的,您可以使用yourArrayAdapter.getPosition(T项)获取索引代码>
最好明确声明并知道您将接收到什么,并利用java使用的类型系统。多亏了krishnas的评论,我意识到我已经从原始教程中的getView方法中删除了以下内容:
songLay.setTag(position);
return songLay;
}
真烦人,我花了3个小时在上面。但是这些论坛的反应非常快,非常棒 在适配器中,有一个函数getItem(position)当前返回null。使用该函数返回单击的列表项详细信息。例如,getItem函数应该是这样的
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return songs.get(arg0);
}
标记的概念是,如果在每个项目列表中都有一个按钮,并将onclicklistener添加到该按钮,那么您就可以这样做
yourButton.setTag(position);
在点击该按钮时,您可以按如下方式检索位置:
yourButton.getTag();
返回的位置将是列表中单击其按钮的行的位置
看看它是否对你有帮助 因此setTag是所有视图用来保存任意引用的一种方便方法:事实上,您可以保存任意数量的引用,只要您使用重载方法,并使用额外的参数为标记分配id
即mView.setTag(mFirstObject)
使用隐式标记id和mView.setTag(R.id.tag1,mSecondObject)代码>使用显式的R.id.tag1
标记id
要检索mFirstObject
,首先使用语句Object=mView.getTag()
和要检索mSecondObject
,则调用将是objectsecond=mView.getTag(R.id.tag1)代码>(注意这里我假设这两个都是对象,因此不需要强制转换它们)
代码正在崩溃,因为没有使用隐式id分配标记的位置。对于分配的任何视图,您都必须执行以下操作:
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
视窗座;
LinearLayout songLay=(LinearLayout)convertView;
if(songLay==null){
songLay=(LinearLayout)songInf.充气(R.layout.song,父项,false);
//获取视图持有者实例
holder=新的ViewHolder();
//使用艺术家视图和文本视图填充viewholder
holder.songView=(TextView)songLay.findViewById(R.id.song\u title);
holder.artistView=(TextView)songLay.findViewById(R.id.song\u艺术家);
songLay.setTag(R.string.TAG1,支架);
}
否则{
holder=(ViewHolder)songLay.getTag(R.string.TAG1);
}
//使用位置获取歌曲
Song currSong=songs.get(位置);
//获取标题和艺术家字符串
holder.songView.setText(currSong.getSongTitle());
holder.artistView.setText(currSong.getArtist());
/*VVVVVVVVVVVV*/
holder.viewWithOnClick=songPickedInXml.setTag(currSong.getId());
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
返回宋雷;
}
}
其中holder.viewWithOnClick=songPickedInXml
是具有相应onClick属性的视图引用。void(视图视图)
中的View视图
参数是定义了onClick
的视图。例如,如果它是一个按钮,您可以将视图
投射到按钮,而不会使其崩溃;如果您试图将其强制转换为imageview,它将崩溃
但是,我强烈建议您不要特别针对listview项使用onClick。假设用户可以单击整行播放歌曲,只需在listview上使用ItemClickListener,然后在LinearLayout songLay do setTag(currSong.getId())上使用ItemClickListener即可;它应该会起作用。不使用onClick的原因——特别是在本例中——是因为它在运行时引用的视图完全不明确
Doh——每个人都比我先到,但仅供参考,你可以随意推,不只是位置,而是整个uri,如果你喜欢的话
至于使用setTag,请随意使用它!这是一个方便的方法,正是这样的东西。请记住,视图将保留对您放入标记桶中的任何内容的引用,因此不要在其中放入任何超出父活动生命周期的内容,以免泄漏内存 getTag()你在哪里设置了该视图的标记?据我所知,我没有。这是一件让我困惑的事情。它是通过XMLOnClick自动设置的吗?据我所知,如果不在视图上设置标记。盖塔格会还给你的null@CarsonH你能告诉我你是怎么称呼歌曲精选法的吗?谢谢你帮我找到了答案!!!我试试这个。我读了一些其他的评论,标签很容易被忽略。@CarsonH,没错。最好明确声明并知道将接收到什么,并利用java使用的系统类型。
yourButton.getTag();