您好,我使用 AsyncTask 实现了一个简单的 RSS Feed 阅读器,它运行良好。我正在尝试升级我的小 APP 以使用 ASYNCTASKLOADER,以学习如何使用 Loaders。
注意上面的两行代码:
public void onCreate(Bundle savedInstanceState){
班级的RSSMain
...
new getRSSFeeds().execute();
getLoaderManager().initLoader(0, null, callBacks1);
通过取消/注释这两行,我决定使用哪种模式来尝试我的应用程序。当我尝试使用 getLoaderManager 阅读 RSS 提要时,我得到的只是一个空白 Activity。
附上我的代码。我的代码一定有一些概念上的错误,因为我对所有这些东西都不熟悉。有人现在如何解决它?
考虑到我 3 周前开始为 Android 编程,我的代码可能远非完美,因此欢迎提出任何改进意见!
public class RSSMain extends ListActivity {
private ArrayList<rssentry> itemlist2 = null; //LIST OF ALL RSS FEEDS
private RSSListAdaptor2 rssadaptor2 = null; //A SINGLE RSS POST
private String sourceurl=null;
public final static String EXTRA_MESSAGE = "com.example.rssjosh.MESSAGE"; //DECLARE PAYLOAD MESSAGE FOR THE ACTIVITY-CALLING INTENT
private static final int LENGTH_SHORT = 0;
private static final int LENGTH_LONG = 1;
String toastxt="empty...";
Toast toast;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//LoaderManager lmanager = getLoaderManager().initLoader(0, null, new RSSLoaderCallback, getBaseContext());
//getLoaderManager().initLoader(0, savedInstanceState, new RSSLoader(null));
sourceurl="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
itemlist2 = new ArrayList<rssentry>();
getLoaderManager().initLoader(0, null, callBacks1); //CREATES AND INITS. LOADER (ASYNCTASKLOADER MODE)
//new getRSSFeeds().execute();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String s=null;
rssentry data = itemlist2.get(position); //GET THE RSSENTRY THAT WAS TOUCHED BY THE USER
//TEMPORARY TOAST TO CHECK CORRECT STRING FORMATION
//String toastxt="XD!";
//int duration = Toast.LENGTH_LONG; //toastxt=toastxt+data.title+"\n"+data.published+"\n"+data.link+"\n"+data.summary.substring(30,140)+"\n";
//FORM THE HTML TEXT TO BE SENT TO THE SIGLE-RSSFEED DISPLAY ACTIVITY
StringBuilder htmlString = new StringBuilder();
htmlString.append(data.title+"$");
htmlString.append("Published on: "+data.published+"$");
htmlString.append(data.summary+"$");
htmlString.append("URL: "+data.link+"$");
Intent intent = new Intent(this,Rssactivity.class);
//LOADS THE INTENT WITH THE <HTML> PAYLOAD
intent.putExtra(EXTRA_MESSAGE, htmlString.toString()); ///public final static String EXTRA_MESSAGE = "com.example.rssjosh.MESSAGE"; DECLARED ABOVE
startActivity(intent); //LAUNCHES INTENT
}
//SERVICE METHOD TO private String retrieveRSSFeed2(String urlToRssFeed)
// _URLstring -> INPUT_STREAM
private InputStream downloadUrl(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// STARTS QUERYING THE STREAM
conn.connect();
InputStream stream = conn.getInputStream();
return stream;
}
//URL -> (INPUT_STREAM) -> List<rssentry> entries
//THIS VARIANT OF THE RETRIEVERSSFEED2 METHOD, RETURNS RESULT IN A STRING FORMAT (OPTIONAL METHOD)
private ArrayList<rssentry> retrieveRSSFeed2Str(String urlToRssFeed) throws XmlPullParserException, IOException
{
ArrayList<rssentry> itemlist = new ArrayList<rssentry>();
//INSTANTIATES A NEW PARSER "parsero", AND AN EMPTY RSSENTRY ARRAYLIST
InputStream stream = null;
//List<rssentry> entries = null; UPGRADED TO PUBLIC CLASS ATTRIBUTE
xmlparser parsero = new xmlparser();
//This Try does URL->Stream
try {
stream = downloadUrl(urlToRssFeed); //OBTAIN A CHARACTER STREAM FROM THE rssURL
itemlist = parsero.parse(stream); //PARSE STREAM AND STORE rssENTRIES IN THE "ENTRIES" ARRAYLIST <rssentry>
} finally {
if (stream != null) {
stream.close(); //CLOSE STREAM AFTER USING IT
}
}
return itemlist;
}
//GETS RSS FEED IN ASYNCHRONOUS MODE
class ATLgetfeeds extends AsyncTaskLoader <ArrayList<rssentry>>{
private ArrayList<rssentry> rsslist=null;
private ProgressDialog progress = null;
public ATLgetfeeds(Context context) {
super(context);
}
@Override
protected void onStartLoading() {
if (rsslist != null)
deliverResult(rsslist); // Use the cache
else
forceLoad();
}
@Override
public ArrayList<rssentry> loadInBackground() {
try {
itemlist2 = null; //<=THIS LIST IS TO BE LOADED WITH THE RSS URL BELOW
rsslist = retrieveRSSFeed2Str("http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest"); //SETS ITEMLIST2
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//LOADS DATA INTO RSSADAPTER (PARSER2)
rssadaptor2 = new RSSListAdaptor2(RSSMain.this, R.layout.rssitemview,rsslist);
return null;
}
@Override
public void deliverResult(ArrayList<rssentry> data) {
rsslist = data; // Caching
super.deliverResult(data);
}
@Override
protected void onReset() {
super.onReset();
// Stop the loader if it is currently running
onStopLoading();
rsslist = null;
}
@Override
public void onCanceled(ArrayList<rssentry> data) {
// Attempt to cancel the current async load
super.onCanceled(data);
rsslist = null;
}
protected void onPreExecute() {
progress = ProgressDialog.show( RSSMain.this, null, "RSSJosh Loading..."); //LOADING MESSAGE
// super.onPreExecute();
}
protected void onPostExecute(Void result) {
itemlist2=rsslist;
setListAdapter(rssadaptor2);
progress.dismiss(); //Dismisses loading progress dialog
//s super.onPostExecute(result);
}
}
//GETS RSS FEED IN ASYNCHRONOUS MODE
private class getRSSFeeds extends AsyncTask<Void, Void, Void>
{
private ProgressDialog progress = null;
ArrayList<rssentry> atlist = new ArrayList<rssentry>();
@Override
protected Void doInBackground(Void... params) {
try {
itemlist2 = null; //<=THIS LIST IS TO BE LOADED WITH THE RSS URL BELOW
atlist = retrieveRSSFeed2Str("http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest");
} catch (XmlPullParserException e) {
e.printStackTrace(); // TODO Auto-generated catch block
} catch (IOException e) {
e.printStackTrace(); // TODO Auto-generated catch block
}
//LOADS DATA INTO UI RSSADAPTER (PARSER2)
rssadaptor2 = new RSSListAdaptor2(RSSMain.this, R.layout.rssitemview,atlist);
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected void onPreExecute() {
progress = ProgressDialog.show( RSSMain.this, null, "RSSJosh Loading..."); //LOADING MESSAGE
super.onPreExecute();
}
@Override
protected void onPostExecute(Void result) {
setListAdapter(rssadaptor2);
itemlist2=atlist;
progress.dismiss(); //Dismisses loading progress dialog
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
//RSS ADAPTER (TYPE2) FOR STACK-OVERFLOW RSSFEEDS
private class RSSListAdaptor2 extends ArrayAdapter<rssentry>{
private List<rssentry> objects = null;
public RSSListAdaptor2(Context context, int textviewid, List<rssentry> objects) {
super(context, textviewid, objects);
this.objects = objects;
}
@Override
public int getCount() {
return ((null != objects) ? objects.size() : 0);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public rssentry getItem(int position) {
return ((null != objects) ? objects.get(position) : null);
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(null == view)
{
LayoutInflater vi = (LayoutInflater)RSSMain.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.rssitemview, null);
}
rssentry data = objects.get(position);
if(null != data)
{ //CREATE TEXTVIEW OBJECTS FORTITLE, DATE AND DESCRIPTION DATA
TextView title = (TextView)view.findViewById(R.id.txtTitle);
TextView date = (TextView)view.findViewById(R.id.txtDate);
TextView description = (TextView)view.findViewById(R.id.txtDescription);
//PUT TEXT ON TITLE AND DATE VIEWS
title.setText(data.title);
date.setText("Published on: " + data.published); //PREVIOUSLY date.setText("on " + data.date);
//PREPARE AND LOAD TEXT FOR THE SUMMARY VIEW
String txt=null;
//Clean and trim summary string before displaying
txt=data.summary.toString().substring(30,data.summary.toString().length());
if (txt.length()>=300)
txt=txt.substring(0,299)+"..."; ///DISPLAY A SUMMARY OF 300 CHARACTERS MAX, IN THE RSS HEADLINES
description.setText(txt); //PUT TEXT
}
return view;
}
}
LoaderManager.LoaderCallbacks<ArrayList<rssentry>> callBacks1 = new LoaderManager.LoaderCallbacks<ArrayList<rssentry>>() {
/* Implement the three callback methods here */
public android.content.Loader<ArrayList<rssentry>> onCreateLoader( //START LOADING
int arg0, Bundle arg1) {
// TODO Auto-generated method stub
android.content.Loader<ArrayList<rssentry>> rsslist=null;
//TEMPORARY TOAST TO DEBUG CORRECT STRING FORMATION
toastxt="Toastiee! Preparing for ATL Task";
toast = Toast.makeText(getBaseContext(), toastxt, LENGTH_SHORT);
toast.show();
ATLgetfeeds a= new ATLgetfeeds(getBaseContext());
//TEMPORARY TOAST TO DEBUG CORRECT STRING FORMATION
toastxt="Toastiee! ATL Task created";
toast = Toast.makeText(getBaseContext(), toastxt, LENGTH_SHORT);
toast.show();
return rsslist;
}
@Override
public void onLoadFinished( //START LOADING
android.content.Loader<ArrayList<rssentry>> arg0,
ArrayList<rssentry> arg1) {
// TODO Auto-generated method stub
}
@Override
public void onLoaderReset(android.content.Loader<ArrayList<rssentry>> arg0) {
// TODO Auto-generated method stub
}
};
}