好吧,我已经被困了几天,并决定来这里寻求帮助。
我正在使用twitter4j库使用寻呼机(寻呼类)一次从usertimeline 10加载状态
我的问题来自于当我尝试使用enlessScrollListener到达底部时更新列表视图,我成功获得更多推文并在适配器中调用补充方法但是适配器拒绝重新填充,
我注意到当我使用新的更新列表调用refill方法时,旧列表会成功清除,但适配器中的addAll()方法会产生一个空列表,并且适配器无法适应任何条件,从而导致一个空的视图,。
一个奇怪的问题是,在PostExecute方法中,如果我将新数据附加到列表的开头而不是使用addAll()方法,那么适配器将成功显示列表,但是会以混乱的顺序显示。
如果可能的话,我很想知道在用户滚动到底部时加载旧推文的更好方法。
很抱歉很长的帖子我是Android开发的新手,并且真的在这个哈哈睡过头了。
以下是片段中的代码:
package com.dise.weekone.feed;
import java.util.List;
import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.OAuth2Token;
import twitter4j.conf.ConfigurationBuilder;
import android.content.Context;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.dise.weekone.R;
import com.dise.weekone.adapters.EndlessScrollListener;
import com.dise.weekone.adapters.FeedAdapter;
import com.dise.weekone.util.BaseFragment;
import com.dise.weekone.util.Const;
public class FeedFragment extends BaseFragment {
protected final static String ScreenName = Const.UON_TWITTER_NAME;
// protected Twitter twits;
// protected DownloadTwitterTask downloadTwitterTask;
Paging pager = new Paging(1, 10);
int pagecount = 1;
protected FeedAdapter adapter;
protected ProgressBar progressBar;
protected List<Status> statuses;
protected SwipeRefreshLayout swipeLayout;
protected Typeface defaultFont;
protected DownloadTwitterTask downloadTwitterTask;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment_feed, container,
false);
ab.setTitle(R.string.twitter_tab_title);
progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar1);
progressBar.setVisibility(View.VISIBLE);
swipeLayout = (SwipeRefreshLayout) rootView
.findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(mOnRefreshListener);
swipeLayout.setColorScheme(R.color.category_mature_color,
R.color.category_free_color, R.color.category_off_campus_color,
R.color.category_night_out_color);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
downloadTweets();
}
@Override
public void onDetach() {
super.onDetach();
if (downloadTwitterTask != null)
downloadTwitterTask.cancel(true);
}
public void downloadTweets() {
ConnectivityManager connMgr = (ConnectivityManager) mainActivity
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
downloadTwitterTask = new DownloadTwitterTask();
downloadTwitterTask.execute(ScreenName);
} else {
Log.v(null, "No network connection available.");
}
}
protected void adaptData() {
progressBar.setVisibility(View.INVISIBLE);
if (swipeLayout.isRefreshing()) {
Log.i(null, "refresh called");
swipeLayout.setRefreshing(false);
((FeedAdapter) getListView().getAdapter()).refillTweets(statuses);
}
if (getListView().getAdapter() == null) {
Log.i(null, "firstlistview called");
adapter = new FeedAdapter(getActivity(), statuses);
getListView().setOnScrollListener(new endlessScrollListener());
getListView().setAdapter(adapter);
} else {
Log.i(null, "refill called");
Log.i(null, "status amount sent: " + statuses.size());
((FeedAdapter) getListView().getAdapter()).refillTweets(statuses);
}
}
protected class DownloadTwitterTask extends
AsyncTask<String, Void, List<twitter4j.Status>> {
@Override
protected List<twitter4j.Status> doInBackground(String... arg0) {
return getUserTimeline();
}
@Override
protected void onPostExecute(List<twitter4j.Status> result) {
if (statuses != null) {
statuses.addAll(result);
} else {
statuses = result;
}
adaptData();
}
private List<twitter4j.Status> getUserTimeline() {
List<twitter4j.Status> tempStatuses = null;
try {
// gets Twitter instance with default credentials\
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("B4V****************xC")
.setOAuthConsumerSecret(
"skIOI***************************HcR")
.setApplicationOnlyAuthEnabled(true); // IMPORTANT: set
// T4J to use
// App-only auth
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
OAuth2Token token = twitter.getOAuth2Token();
String user = "ScreenNameforTwitterAccount";
pager.setPage(pagecount);
tempStatuses = twitter.getUserTimeline(user, pager);
} catch (TwitterException te) {
te.printStackTrace();
Log.e(null, "failed to get timeline");
}
return tempStatuses;
}
}
public class endlessScrollListener extends EndlessScrollListener {
@Override
public void onLoadMore(int page, int totalItemsCount) {
customLoadMoreDataFromApi(page);
}
// Append more data into the adapter
public void customLoadMoreDataFromApi(int offset) {
// This method probably sends out a network request and appends new
// data items to your adapter.
// Use the offset value and add it as a parameter to your API
// request to retrieve paginated data.
// Deserialize API response and then construct new objects to append
// to the adapter
Log.i(null, "offset = " + offset);
pagecount = offset;
downloadTweets();
}
}
protected OnRefreshListener mOnRefreshListener = new OnRefreshListener() {
@Override
public void onRefresh() {
downloadTweets();
}
};
}
FeedAdapter.java
package com.dise.weekone.adapters;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import twitter4j.Status;
import android.content.Context;
import android.graphics.Typeface;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.dise.weekone.R;
import com.dise.weekone.ui.MainActivity;
public class FeedAdapter extends GenericAdapter<Status> {
protected Context mContext;
protected List<Status> statusList;
protected ViewHolder holder;
protected Typeface defaultFont;
protected String regexAgo = "\\s*\\bago\\b\\s*",
regexhr = "\\s*\\bhours\\b\\s*", regexDay = "\\s*\\bdays\\b\\s*",
regexmin = "\\s*\\bminutes\\b\\s*",
regexYes = "\\s*\\bYesterday\\b\\s*";
public FeedAdapter(Context context, List<Status> statuses) {
super((MainActivity) context, statuses);
defaultFont = Typeface.createFromAsset(context.getAssets(),
"ufonts.com_gillsans.ttf");
mContext = context;
statusList = statuses;
}
@Override
public View getDataRow(int position, View convertView, ViewGroup parent) {
// ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.feed_item, parent, false);
holder = new ViewHolder();
holder.hashtag = (TextView) convertView
.findViewById(R.id.hashtagLabel);
holder.hashtag.setTypeface(defaultFont);
holder.tweet = (TextView) convertView.findViewById(R.id.tweetLabel);
holder.tweet.setTypeface(defaultFont);
holder.time = (TextView) convertView.findViewById(R.id.timeLabel);
holder.time.setTypeface(defaultFont);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Status tweet = statusList.get(position);
String tweetText = tweet.getText();
holder.tweet.setText(tweetText);
holder.time.setText(convertRelativeTime(tweet.getCreatedAt()));
return convertView;
}
protected String convertRelativeTime(Date time) {
final String TWITTER = "EEE MMM dd HH:mm:ss ZZZZZ yyyy";
SimpleDateFormat sf = new SimpleDateFormat(TWITTER, Locale.ENGLISH);
sf.setLenient(true);
long now = new Date().getTime();
String convertedDate = DateUtils.getRelativeTimeSpanString(
time.getTime(), now, DateUtils.MINUTE_IN_MILLIS).toString();
return parseDate(convertedDate);
}
protected String parseDate(String oldDate) {
String parsedDate = oldDate.replaceAll(regexAgo, "");
if (parsedDate.contains("minutes")) {
parsedDate = parsedDate.replaceAll(regexmin, "m");
} else if (parsedDate.contains("hours")) {
parsedDate = parsedDate.replaceAll(regexhr, "h");
} else if (parsedDate.contains("Yesterday")) {
parsedDate = parsedDate.replaceAll(regexYes, "1d");
} else if (parsedDate.contains("days")) {
parsedDate = parsedDate.replaceAll(regexDay, "d");
} else if (parsedDate.length() > 4) {
final String dateFormat = "MMMdd,yyyy";
SimpleDateFormat sf = new SimpleDateFormat(dateFormat,
Locale.ENGLISH);
sf.setLenient(true);
Date tempDate;
try {
tempDate = sf.parse(parsedDate);
parsedDate = (String) android.text.format.DateFormat.format(
"dd/MM/yy", tempDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
parsedDate.replaceAll(" ", "");
return parsedDate;
}
private static class ViewHolder {
TextView hashtag;
TextView tweet;
TextView time;
}
public void refillTweets(List<Status> twitterNew) {
List<Status> newList = twitterNew;
statusList.clear();
statusList.addAll(twitterNew);
notifyDataSetChanged();
}
}