Android无尽列表视图在使用专用线程获取新内容后不更新
我使用电脑有问题 请注意,我正在使用支持库和操作栏sherlock(我的问题可能与此无关)。 我的自定义适配器在SherlockListFragment中运行良好(扩展了BaseAdapter) 当我向下滚动并最终获取新内容(使用自己的类扩展线程)时,一切似乎都正常工作(任务在DemoAdapter(extends EndlessAdapter)的onItemsReady()中返回),新内容在那里(不显示,但对象不是空的,并添加到我的对象中) 因此,当我调用onDataReady()时,什么也没有发生。我已经为这个问题挣扎了几个小时 你看到我的代码中有什么错误吗?没有错误,新内容就是不显示 片段类Android无尽列表视图在使用专用线程获取新内容后不更新,android,commonsware-cwac,Android,Commonsware Cwac,我使用电脑有问题 请注意,我正在使用支持库和操作栏sherlock(我的问题可能与此无关)。 我的自定义适配器在SherlockListFragment中运行良好(扩展了BaseAdapter) 当我向下滚动并最终获取新内容(使用自己的类扩展线程)时,一切似乎都正常工作(任务在DemoAdapter(extends EndlessAdapter)的onItemsReady()中返回),新内容在那里(不显示,但对象不是空的,并添加到我的对象中) 因此,当我调用onDataReady()时,什么也没
public class BusinessListFragment extends SherlockListFragment {
private DemoAdapter adapter;
static public List<Business> items;
public static final String TAG = BusinessListFragment.class.getName();
public interface IItemsReadyListener {
public void onItemsReady(List<Business> data);
}
public BusinessListFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_business_list, null);
return view;
}
@Override
public void onViewCreated(View arg0, Bundle arg1) {
super.onViewCreated(arg0, arg1);
RestoApplication app = (RestoApplication) (getActivity().getApplication());
if (adapter == null) {
adapter = new DemoAdapter(getSherlockActivity(), app, items);
adapter.setRunInBackground(false);
}
setListAdapter(adapter);
}
static public void start() {
}
}
抽象类(解析并在完成时调用侦听器)
公共抽象类AbstractSearchBusinessLoader扩展线程{
受保护的处理程序;
受保护的搜索侦听器;
受保护的项目亚迪斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯勒斯;
保护上下文ctx;
受保护的字符串路径;
private List businessList=new ArrayList();
公共接口SearchBusinessListener{
搜索结果(列表bizList)上的公共无效;
}
受保护的最终静态字符串LOG_TAG=AbstractSearchBusinessLoader.class.getSimpleName();
公共最终静态int MSG_ERROR=201;
公共最终静态int MSG_FINISHED=200;
公共最终静态字符串BUNDLE\u KEY\u ERROR=“bundleKeyError”;
抽象InputStream getStream()抛出IOException,Exception;
@凌驾
公开募捐{
InputStream=null;
试一试{
stream=getStream();
}捕获(IOE异常){
Log.e(Log_标记,“获取时IOException:”+path,e);
handler.sendEmptyMessage(MSG_错误);
返回;
}捕获(例外e){
Log.e(Log_标记,“获取时异常:”+path,e);
handler.sendEmptyMessage(MSG_错误);
返回;
}
试一试{
XmlPullParserFactory工厂=XmlPullParserFactory.newInstance();
XmlPullParser=factory.newPullParser();
setInput(流,空);
parser.next();
而(!(parser.getEventType()==XmlPullParser.END_标记和&XmlTags.SEARCHRESPONSE.equals(XmlTags.fromString(parser.getName())){
if(parser.getEventType()==XmlPullParser.START_TAG&&XmlTags.TOTALRESULTS.equals(XmlTags.fromString(parser.getName())){
字符串totalRes=parser.nextText();
}
if(parser.getEventType()==XmlPullParser.START_TAG&&XmlTags.SEARCHSEED.equals(XmlTags.fromString(parser.getName())){
字符串searchSeed=parser.nextText();
}
if(parser.getEventType()==XmlPullParser.START_TAG&&XmlTags.businesss.equals(XmlTags.fromString(parser.getName())){
解析器(解析器);
}
parser.next();
}
}catch(XMLPullParseRexE){
Log.e(Log_标记,“处理业务结果xml时的XmlPullParserException”,e);
handler.sendEmptyMessage(MSG_错误);
返回;
}捕获(IOE异常){
Log.e(Log_标签,“处理业务结果xml时IOException”,e);
handler.sendEmptyMessage(MSG_错误);
返回;
}
if(侦听器!=null){
onSearchResult(businessesList);
}
if(endlessListener!=null){
Log.d(Log_标签,“endlessListener:onItemsReady”);
endlessListener.onItemsReady(业务列表);
}
}
私有void parseBusinesss(XmlPullParser解析器)抛出XmlPullParserException,IOException{
...
}
私有列表ParseCusines(XmlPullParser)抛出XmlPullParserException,IOException{
...
}
私有列表parsePictures(XmlPullParser解析器)抛出XmlPullParserException,IOException{
....
}
私有void parseBusiness(XmlPullParser)抛出XmlPullParserException,IOException{
...
}从
setDataFromAnyThread()
中删除您的Runnable
,如onitem就绪()在主应用程序线程上调用
,看看这是否有帮助。感谢@commonware的建议,但我有android.view.ViewRootImpl$CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图。如果我这样做。(OnItemReady()在我编写的类(扩展线程)的侦听器上调用,那么您正在做一些非常奇怪的事情。如果查看repo中的demo/
项目,您将看到它不需要使用post()
。但是如果我在自己的线程中使用自己的自定义类来获取新数据,我不能接触UI线程不是很正常吗?我将在下面发布代码,让您看看我是怎么做的。如果您能很高兴地看一看,也许您的帮助不仅可以修复我的错误,还可以提高我的编码技能。(我已经安装了演示项目并深入研究了它,同时也从中获得了灵感(更新了我的问题,以便您可以看到我如何获取数据)。您认为它有什么问题吗?非常感谢。
public class DemoAdapter extends EndlessAdapter implements IItemsReadyListener {
private RotateAnimation rotate = null;
ArrayList<String> tempList = new ArrayList<String>();
private final Context ctx;
private final RestoApplication app;
private List<Business> items;
private static final String LOG_TAG = DemoAdapter.class.getName();
private boolean hasMoreData = false;
private int page = 1;
final Handler mHandler = new Handler();
void setDataFromAnyThread(final List<Business> newData) {
// Enqueue work on mHandler to change the data on
// the main thread.
mHandler.post(new Runnable() {
@Override
public void run() {
items.addAll(newData);
onDataReady();
hasMoreData = items.isEmpty();
Log.d(LOG_TAG, "ok done, items size: " + items.size());
}
});
}
public DemoAdapter(Context ctx, RestoApplication app, List<Business> items) {
super(new SearchBusinessAdapter(ctx, app, items));
this.ctx = ctx;
this.app = app;
this.items = new LinkedList<Business>(items);
rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(600);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);
page++; // the moment cacheInBackground will be called for the first
// time we'll need to download page 2;
}
@Override
protected View getPendingView(ViewGroup parent) {
View row = LayoutInflater.from(ctx).inflate(R.layout.list_item_business, null);
View child = row.findViewById(R.id.info_container);
child.setVisibility(View.GONE);
child = row.findViewById(R.id.throbber);
child.setVisibility(View.VISIBLE);
child.startAnimation(rotate);
return (row);
}
@Override
protected boolean cacheInBackground() {
Log.d(LOG_TAG, "cacheInBackground");
String path = new SearchBuinessUrlBuilder().businessType("1").lang(AbstractActivity.FRENCH).pageNumber(page).location("londres").build();
new SearchBusinessLoader(mHandler, DemoAdapter.this, ctx, path).start();
return hasMoreData;
}
@Override
protected void appendCachedData() {
Log.d(LOG_TAG, "appendCachedData");
}
@Override
public void onItemsReady(final List<Business> data) {
Log.d(LOG_TAG, "onItemsReady in DemoAdapter new data.size()= "+data.size());
setDataFromAnyThread(data);
page++;
}
}
public class SearchBusinessAdapter extends BaseAdapter {
private final static String BUS_TAG = SearchBusinessAdapter.class.getSimpleName();
private final static String LOG_TAG = SearchBusinessAdapter.class.getSimpleName();
private final Context ctx;
private final RestoApplication app;
private final List<Business> items;
public SearchBusinessAdapter(Context ctx, RestoApplication app, List<Business> items) {
this.ctx = ctx;
this.items = new LinkedList<Business>(items);
this.app = app;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
view = LayoutInflater.from(ctx).inflate(R.layout.list_item_business, null);
} else {
view = convertView;
}
Business item = items.get(position);
ImageView imgThumbmail = ((ImageView) view.findViewById(R.id.newsListItemThumbnail));
imgThumbmail.setImageDrawable(ctx.getResources().getDrawable(R.drawable.ic_launcher));
TextView nameTf = ((TextView) view.findViewById(R.id.name));
FontsWrapper.setBoldTf(ctx, new TextView[] { nameTf });
nameTf.setText(item.getName());
TextView adressTf = ((TextView) view.findViewById(R.id.adress));
FontsWrapper.setCondensedTf(ctx, new TextView[] { adressTf });
StringBuilder adressSb = new StringBuilder();
adressSb.append(item.getStreet());
adressSb.append("\n");
adressSb.append(item.getZip() + " " + item.getCity());
adressTf.setText(adressSb.toString());
TextView cuisineTypeTf = ((TextView) view.findViewById(R.id.cuisineType));
FontsWrapper.setLightTf(ctx, new TextView[] { cuisineTypeTf });
StringBuilder cuisinesSb = new StringBuilder();
cuisinesSb.append(ctx.getText(R.string.cuisine_type_label));
cuisinesSb.append(": ");
if (item.getCuisinesList() != null) {
for (int i = 0; i < item.getCuisinesList().size(); i++) {
cuisinesSb.append(item.getCuisinesList().get(i).getCuisine());
if (i < item.getCuisinesList().size() - 1) {
cuisinesSb.append(", ");
}
}
} else {
cuisinesSb.append("/");
}
cuisineTypeTf.setText(cuisinesSb);
return view;
}
}
public class SearchBusinessLoader extends AbstractSearchBusinessLoader {
static final String LOG_TAG = SearchBusinessLoader.class.getSimpleName();
public SearchBusinessLoader(Handler handler, SearchBusinessListener listener, Context ctx, String path) {
super();
super.ctx = ctx;
this.handler = handler;
this.listener = listener;
this.path = path;
}
public SearchBusinessLoader(Handler handler, IItemsReadyListener listener, Context ctx, String path) {
super();
super.ctx = ctx;
this.handler = handler;
this.endlessListener = listener;
this.path = path;
}
@Override
InputStream getStream() throws IOException, Exception {
DefaultHttpClient client = new DefaultHttpClient();
Log.d(LOG_TAG, "path= "+path);
HttpGet request = new HttpGet(path);
HttpResponse response = client.execute(request);
return response.getEntity().getContent();
}
}
public abstract class AbstractSearchBusinessLoader extends Thread {
protected Handler handler;
protected SearchBusinessListener listener;
protected IItemsReadyListener endlessListener;
protected Context ctx;
protected String path;
private List<Business> businessesList = new ArrayList<Business>();
public interface SearchBusinessListener {
public void onSearchResult(List<Business> bizList);
}
protected final static String LOG_TAG = AbstractSearchBusinessLoader.class.getSimpleName();
public final static int MSG_ERROR = 201;
public final static int MSG_FINISHED = 200;
public final static String BUNDLE_KEY_ERROR = "bundleKeyError";
abstract InputStream getStream() throws IOException, Exception;
@Override
public void run() {
InputStream stream = null;
try {
stream = getStream();
} catch (IOException e) {
Log.e(LOG_TAG, "IOException while getting: " + path, e);
handler.sendEmptyMessage(MSG_ERROR);
return;
} catch (Exception e) {
Log.e(LOG_TAG, "Exception while getting: " + path, e);
handler.sendEmptyMessage(MSG_ERROR);
return;
}
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(stream, null);
parser.next();
while (!(parser.getEventType() == XmlPullParser.END_TAG && XmlTags.SEARCHRESPONSE.equals(XmlTags.fromString(parser.getName())))) {
if (parser.getEventType() == XmlPullParser.START_TAG && XmlTags.TOTALRESULTS.equals(XmlTags.fromString(parser.getName()))) {
String totalRes = parser.nextText();
}
if (parser.getEventType() == XmlPullParser.START_TAG && XmlTags.SEARCHSEED.equals(XmlTags.fromString(parser.getName()))) {
String searchSeed = parser.nextText();
}
if (parser.getEventType() == XmlPullParser.START_TAG && XmlTags.BUSINESSES.equals(XmlTags.fromString(parser.getName()))) {
parseBusinesses(parser);
}
parser.next();
}
} catch (XmlPullParserException e) {
Log.e(LOG_TAG, "XmlPullParserException while processing business result xml", e);
handler.sendEmptyMessage(MSG_ERROR);
return;
} catch (IOException e) {
Log.e(LOG_TAG, "IOException while processing business result xml", e);
handler.sendEmptyMessage(MSG_ERROR);
return;
}
if (listener != null) {
listener.onSearchResult(businessesList);
}
if (endlessListener != null) {
Log.d(LOG_TAG, "endlessListener : onItemsReady");
endlessListener.onItemsReady(businessesList);
}
}
private void parseBusinesses(XmlPullParser parser) throws XmlPullParserException, IOException {
...
}
private List<Cuisine> parseCuisines(XmlPullParser parser) throws XmlPullParserException, IOException {
...
}
private List<Picture> parsePictures(XmlPullParser parser) throws XmlPullParserException, IOException {
....
}
private void parseBusiness(XmlPullParser parser) throws XmlPullParserException, IOException {
...