Java 为ListView使用自定义BaseAdapter-多个片段?
我已经成功地组装了一个定制的BaseAdapter。此适配器用于显示每个列表项的三个文本视图。当“活动”中有一个ListView时,工作绝对完美 然而,我正在使用一个包含3个片段的片段化活动,其中2个包含一个需要使用自定义适配器和XML的ListView 加载这两个ListView时,在加载的第一个ListView上启动onItemClickListener会导致以下错误:Java 为ListView使用自定义BaseAdapter-多个片段?,java,android,android-listview,android-fragments,android-adapter,Java,Android,Android Listview,Android Fragments,Android Adapter,我已经成功地组装了一个定制的BaseAdapter。此适配器用于显示每个列表项的三个文本视图。当“活动”中有一个ListView时,工作绝对完美 然而,我正在使用一个包含3个片段的片段化活动,其中2个包含一个需要使用自定义适配器和XML的ListView 加载这两个ListView时,在加载的第一个ListView上启动onItemClickListener会导致以下错误: 11-20 18:02:15.295: E/AndroidRuntime(18563): java.lang.Illega
11-20 18:02:15.295: E/AndroidRuntime(18563): java.lang.IllegalStateException:
The content of the adapter has changed but ListView did not receive a
notification. Make sure the content of your adapter is not modified from
a background thread, but only from the UI thread. [in ListView(2131165192,
class android.widget.ListView) with
Adapter(class com.my.project.Adapter_CustomList)]
我不希望适配器发生更改-每个ListView适配器都使用一个新的适配器\u CustomList(),因此我不确定为什么它们被引用为同一个适配器
适配器将getActivity()作为上下文-因为这两者都是相同的,这是导致问题的原因吗?有没有办法解决这个问题,或者这是碎片的另一个缺点
自定义适配器大致如下,我已经取出了一些任意代码块
public class Adapter_CustomList extends BaseAdapter {
private static ArrayList<Custom> results;
private LayoutInflater mInflater;
public Adapter_CustomList(Context context, ArrayList<Custom> res) {
results = res;
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return results.size();
}
public Object getItem(int position) {
return results.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.custom_row_view, null);
holder = new ViewHolder();
//Set ViewHolder vars from inflated view
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//Sets the TextViews
return convertView;
}
static class ViewHolder {
//Contains the TextView text vars
}
}
例如,这两个片段几乎相同,但具有唯一的布局文件
public class Frag_ListOne extends Fragment {
private ListView ListView;
private Adapter_CustomList listAdapter;
private Fetcher fetcher;
public Frag_ListOne(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.frag_list_one, container, false);
}
@Override
public void onStart(){
super.onStart();
ListView = (ListView) getActivity().findViewById(R.id.frag_one_list);
ListView.setEmptyView(getActivity().findViewById(R.id.frag_one_list_spinner));
if (listAdapter != null){
setListAdapter();
} else {
//This will always be called for now....
sendRequest();
}
}
private void sendRequest(){
fetcher = new Fetcher();
fetcher.execute("http://myapiurl.com");
}
private void cancelFetch(){
if (fetcher != null &&
(fetcher.getStatus() == AsyncTask.Status.PENDING || fetcher.getStatus() == AsyncTask.Status.RUNNING)){
fetcher.cancel(true);
}
}
private void displayError(String errMsg){
//Log errMsg
}
private void createListAdapter(ArrayList<Result> res){
listAdapter = new Adapter_CustomList(getActivity(), res);
setListAdapter();
}
private void setListAdapter(){
ListView.setAdapter(listAdapter);
ListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Result r = (Result) ListView.getItemAtPosition(position);
Intent intent = new Intent(getActivity(), ViewResultActivity.class);
intent.putExtra(F_List.INTENT_VIEW_RESULT_OBJ, r);
startActivity(intent);
}
});
}
//Extended AsyncTask, essentially
public class Fetcher extends JSONRequest{
@Override
protected void onSuccess(JSONObject req, JSONObject res){
if (req != null && res != null){
try{
JSONArray jsons = res.getJSONArray("results");
ArrayList<Result> res = new ArrayList<Result>();
if (jsons.length() > 0){
for (int i=0;i<jsons.length();i++){
JSONObject jo = jsons.getJSONObject(i);
r = new Result();
r.setLineOne(jo.getInt("line1"));
r.setLineTwo(jo.getString("line2"));
r.setLineThree(jo.getString("line3"));
res.add(r);
}
createListAdapter(res);
} else {
//Nothing found
}
} catch (JSONException e){}
} else {
//Null received
}
}
@Override
protected void onError(String errMsg){}
@Override
protected void onCancel(){}
}
}
公共类Frag_ListOne扩展片段{
私有列表视图列表视图;
专用适配器\自定义列表列表适配器;
私人取数器取数器;
公共Frag_ListOne(){}
@凌驾
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
返回充气机。充气(R.layout.frag_list_one,容器,错误);
}
@凌驾
public void onStart(){
super.onStart();
ListView=(ListView)getActivity().findViewById(R.id.frag\u one\u list);
setEmptyView(getActivity().findViewById(R.id.frag_one_list_spinner));
if(listAdapter!=null){
setListAdapter();
}否则{
//这将永远是呼吁现在。。。。
sendRequest();
}
}
私有void sendRequest(){
fetcher=新的fetcher();
fetcher.execute(“http://myapiurl.com");
}
私有void cancelFetch(){
if(fetcher!=null&&
(fetcher.getStatus()==AsyncTask.Status.PENDING | | fetcher.getStatus()==AsyncTask.Status.RUNNING)){
fetcher.cancel(true);
}
}
私有void显示错误(字符串errMsg){
//日志错误消息
}
私有void createListAdapter(ArrayList res){
listAdapter=新适配器\自定义列表(getActivity(),res);
setListAdapter();
}
私有void setListAdapter(){
setAdapter(listAdapter);
setOnItemClickListener(新的OnItemClickListener(){
@凌驾
公共视图单击(适配器视图a、视图v、内部位置、长id){
结果r=(结果)ListView.getItemAtPosition(位置);
Intent Intent=new Intent(getActivity(),ViewResultActivity.class);
intent.putExtra(F_List.intent_VIEW_RESULT_OBJ,r);
星触觉(意向);
}
});
}
//扩展异步任务,本质上
公共类获取程序扩展JSONRequest{
@凌驾
成功时受保护的无效(JSONObject请求,JSONObject res){
如果(请求!=null&&res!=null){
试一试{
JSONArray jsons=res.getJSONArray(“结果”);
ArrayList res=新的ArrayList();
if(jsons.length()>0){
对于(inti=0;i适配器代码看起来不错-我做了类似的事情,在不同的片段中运行两个列表视图。(我假设结果实际上等于提供的结果)
也许你附加到列表视图的方式有问题
- 确保适配器和列表视图都在片段中引用,而不是在活动中引用
- 检查是否设置了适配器,然后在不调用adapter.notifyDataSetChanged()的情况下更改驱动它的列表
对于片段和适配器的声明方式更有用:)
编辑:
我正在运行一个系统,在这个系统中,我将使用FragmentManager而不是FragmentPagerAdapter将2个片段充气到框架布局中
我将仔细检查片段是否在片段寻呼机适配器中被正确创建和访问
还要注意getItem(…)的编写方式,因为如果您不断生成新片段,这可能会很快导致内存不足错误。相反,我将介绍如何使用片段管理器和标记来管理新片段的创建
另一个想法是考虑把清单放在滑动抽屉里,这样他们就可以根据需要拉出来。
编辑2:
尝试以下更改-这样列表就存在于片段的内存中,而不是AsyncTask的一部分,而AsyncTask可能会在完成时进行GCed
private ArrayList<Result> resultList = new ArrayList<Result>();
private Adapter_CustomList adapter = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.frag_list_one, container, false);
listView = (ListView) v.findViewById(R.id.frag_one_list);
listView.setEmptyView(v.findViewById(R.id.frag_one_list_spinner));
adapter = new Adapter_CustomList(getActivity(), resultList);
listView.setAdapter(adapter);
}
@Override
public void onStart(){
super.onStart();
}
//Extended AsyncTask, essentially
public class Fetcher extends JSONRequest{
@Override
protected void onSuccess(JSONObject req, JSONObject res){
if (req != null && res != null){
try{
JSONArray jsons = res.getJSONArray("results");
if (jsons.length() > 0){
for (int i=0;i<jsons.length();i++){
JSONObject jo = jsons.getJSONObject(i);
r = new Result();
r.setLineOne(jo.getInt("line1"));
r.setLineTwo(jo.getString("line2"));
r.setLineThree(jo.getString("line3"));
resultList.add(r);
}
adapter.notifyDataSetChanged();
} else {
//Nothing found
}
} catch (JSONException e){}
} else {
//Null received
}
}
@Override
protected void onError(String errMsg){}
@Override
protected void onCancel(){}
}
private ArrayList resultList=new ArrayList();
专用适配器\u CustomList Adapter=null;
@凌驾
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
视图v=充气机。充气(R.layout.frag\u list\u one,容器,假);
listView=(listView)v.findViewById(R.id.frag_one_list);
setEmptyView(v.findViewById(R.id.frag_one_list_spinner));
adapter=newadapter\u CustomList(getActivity(),resultList);
setAdapter(适配器);
}
@凌驾
public void onStart(){
super.onStart();
}
//扩展异步任务,本质上
公共类获取程序扩展JSONRequest{
@凌驾
成功时受保护的无效(JSONObject请求,JSONObject res){
如果(请求!=null&&res!=null){
试一试{
JSONArray jsons=res.getJSONArray(“结果”);
if(jsons.length()>0){
对于(int i=0;iYep,修复了变量名-good spot。为了简单起见,我在此处对其进行了更改。Grr,[Enter]for post在该网站上是一个难题。无论如何,是的,这些变量肯定在片段中引用,而不是在MainActivity(片段所属的活动)中引用。使用.notifyDataSetChanged()在这两个片段中都不起作用(设置适配器后)。可能是
private ArrayList<Result> resultList = new ArrayList<Result>();
private Adapter_CustomList adapter = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.frag_list_one, container, false);
listView = (ListView) v.findViewById(R.id.frag_one_list);
listView.setEmptyView(v.findViewById(R.id.frag_one_list_spinner));
adapter = new Adapter_CustomList(getActivity(), resultList);
listView.setAdapter(adapter);
}
@Override
public void onStart(){
super.onStart();
}
//Extended AsyncTask, essentially
public class Fetcher extends JSONRequest{
@Override
protected void onSuccess(JSONObject req, JSONObject res){
if (req != null && res != null){
try{
JSONArray jsons = res.getJSONArray("results");
if (jsons.length() > 0){
for (int i=0;i<jsons.length();i++){
JSONObject jo = jsons.getJSONObject(i);
r = new Result();
r.setLineOne(jo.getInt("line1"));
r.setLineTwo(jo.getString("line2"));
r.setLineThree(jo.getString("line3"));
resultList.add(r);
}
adapter.notifyDataSetChanged();
} else {
//Nothing found
}
} catch (JSONException e){}
} else {
//Null received
}
}
@Override
protected void onError(String errMsg){}
@Override
protected void onCancel(){}
}