I've created an XML parser which populates a listView with data obtained from an XML file. The problem is for some reason the listView shows the same data over and over instead of unique data for each listView item.
I'm not sure exactly what is causing this issue - any insight is greatly appreciated.
Screenshot:
XML Data:
<response>
<cmd>getVideos</cmd>
<success>1</success>
<NumberOfVideos>4</NumberOfVideos>
<Videos>
<Video>
<VideoName>sample_iPod</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/06087297988b.m4v
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_mpeg4</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/b5ed9e7100e2.mp4
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_sorenson</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/2a8e64b24997.mov
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_iTunes</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/6c7f65254aad.mov
</VideoUrl>
<VideoTags/>
</Video>
</Videos>
</response>
Example/Tutorial:
http://theopentutorials.com/tutorials/android/xml/android-simple-xml-sax-parser-tutorial/
SAXXMLHandler.java
public class SAXXMLHandler extends DefaultHandler {
private List<Cmd> videos;
private String tempVal;
// to maintain context
private Cmd cmd;
public SAXXMLHandler() {
videos = new ArrayList<Cmd>();
}
public List<Cmd> getResponse() {
return videos;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tempVal = "";
if (qName.equalsIgnoreCase("Video")) {
// create a new instance of cmd
cmd = new Cmd();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("videos")) {
// add it to the list
} else if (qName.equalsIgnoreCase("success")) {
cmd.setSuccess(tempVal);
} else if (qName.equalsIgnoreCase("numberofvideos")) {
cmd.setNumberOfVideos(tempVal);
} else if (qName.equalsIgnoreCase("videos")) {
cmd.setVideos(videos);
} else if (qName.equalsIgnoreCase("video")) {
cmd.setVideo(tempVal);
} else if (qName.equalsIgnoreCase("videoname")) {
cmd.setVideoName(tempVal);
} else if (qName.equalsIgnoreCase("videourl")) {
cmd.setVideoURL(tempVal);
videos.add(cmd); //You only need store an instance of your Cmd
}
}
}
CustomListViewAdapter.java
public class CustomListViewAdapter extends ArrayAdapter<Cmd> {
Activity context;
List<Cmd> videos;
public CustomListViewAdapter(Activity context, List<Cmd> videos) {
super(context, R.layout.list_item2, videos);
this.context = context;
this.videos = videos;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtSuccess;
TextView txtCmd;
TextView txtPrice;
}
public Cmd getItem(int position) {
return videos.get(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item2, null);
holder = new ViewHolder();
holder.txtSuccess = (TextView) convertView.findViewById(R.id.success);
holder.txtCmd = (TextView) convertView.findViewById(R.id.cmd);
holder.txtPrice = (TextView) convertView.findViewById(R.id.price);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbnail);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Cmd cmd = (Cmd) getItem(position);
holder.txtSuccess.setText(cmd.getSuccess());
holder.txtCmd.setText(cmd.getCmd());
// holder.imageView.setImageBitmap(cmd.getImageBitmap());
holder.txtPrice.setText(cmd.getVideoName() + "");
return convertView;
}
}
SAXParserAsyncTaskActivity.java
public class SAXParserAsyncTaskActivity extends Activity implements
OnClickListener, OnItemClickListener {
Button button;
ListView listView;
List<Cmd> videos = new ArrayList<Cmd>();
CustomListViewAdapter listViewAdapter;
static final String URL = "http://mobile.example.com/api/xmlrpc.php?cmd=getVideos&username=fake&password=credential";
public static final String LIBRARY = "Library";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parser_main);
findViewsById();
button.setOnClickListener(this);
listView.setOnItemClickListener(this);
GetXMLTask task = new GetXMLTask(this);
task.execute(new String[] { URL });
}
private void findViewsById() {
button = (Button) findViewById(R.id.button);
listView = (ListView) findViewById(R.id.cmdList);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
#Override
public void onClick(View view) {
// GetXMLTask task = new GetXMLTask(this);
// task.execute(new String[] { URL });
}
// private inner class extending AsyncTask
private class GetXMLTask extends AsyncTask<String, Void, List<Cmd>> {
private Activity context;
public GetXMLTask(Activity context) {
this.context = context;
}
protected void onPostExecute(List<Cmd> videos) {
listViewAdapter = new CustomListViewAdapter(context, videos);
listView.setAdapter(listViewAdapter);
}
/*
* uses HttpURLConnection to make Http request from Android to download
* the XML file
*/
private String getXmlFromUrl(String urlString) {
StringBuffer output = new StringBuffer("");
try {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(stream));
String s = "";
while ((s = buffer.readLine()) != null)
output.append(s);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return output.toString();
}
#Override
protected List<Cmd> doInBackground(String... urls) {
List<Cmd> videos = null;
String xml = null;
for (String url : urls) {
xml = getXmlFromUrl(url);
InputStream stream = new ByteArrayInputStream(xml.getBytes());
videos = SAXXMLParser.parse(stream);
if ( videos == null) {
Toast.makeText(getApplicationContext(), "Videos is null!)",
Toast.LENGTH_LONG).show();
}
for (Cmd cmd : videos) {
String videoName = cmd.getVideoName();
// String getVideos = cmd.getVideos();
// String getVideo = cmd.getVideo();
// String getVideoURL = cmd.getVideoURL();
// String getNumberOfVideos = cmd.getNumberOfVideos();
//
// Bitmap bitmap = null;
// BitmapFactory.Options bmOptions = new BitmapFactory.Options();
// bmOptions.inSampleSize = 1;
//
// try {
// bitmap = BitmapFactory.decodeStream(
// new URL(videoName).openStream(), null,
// bmOptions);
// } catch (MalformedURLException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
// stream.close();
return videos;
}
}
}
You are creating only one instance of Cmd() that is overriding itself, because you have only one <cmd> element.
Change:
if (qName.equalsIgnoreCase("cmd")) {
// create a new instance of cmd
cmd = new Cmd();
}
to:
if (qName.equalsIgnoreCase("Video")) {
// create a new instance of cmd
cmd = new Cmd();
}
You need to create an instance of Cmd() when your parser read every <Video> element.
and change your endElement(String uri, String localName, String qName) method to:
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("videos")) {
// add it to the list
/*} else if (qName.equalsIgnoreCase("success")) {
cmd.setSuccess(tempVal);
} else if (qName.equalsIgnoreCase("numberofvideos")) {
cmd.setNumberOfVideos(tempVal);
} else if (qName.equalsIgnoreCase("videos")) {
cmd.setVideos(videos);
} else if (qName.equalsIgnoreCase("video")) {
cmd.setVideo(tempVal);*/
} else if (qName.equalsIgnoreCase("videoname")) {
cmd.setVideoName(tempVal);
} else if (qName.equalsIgnoreCase("videourl")) {
cmd.setVideoURL(tempVal);
videos.add(cmd); //You only need store an instance of your Cmd
}
}
Related
The adapter shows only one item will JSON has more than that number how can the adapter shows all the JSON elements? i have loader and it is only shows one element and repeat it?
the JSON ger elements doesn't show in the adapter I tried things but it doesn't work !! how can I show and take every single element from the response.
the image shows the elements
the adapter:
public class shelfsAdapter extends ArrayAdapter < shelfs > {
public shelfsAdapter(MainActivity context, ArrayList < shelfs > objects) {
super(context, 0, objects);
}#
Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItem = convertView;
if (listItem == null) {
listItem = LayoutInflater.from(getContext())
.inflate(R.layout.item, parent, false);
}
shelfs current = getItem(position);
TextView title = (TextView) listItem.findViewById(R.id.title);
title.setText(current.getTitle());
TextView author = (TextView) listItem.findViewById(R.id.author);
author.setText(current.getAuthors());
return listItem;
}
}
the loader:
public class LoaderApp extends AsyncTaskLoader<List<shelfs>> {
private String url;
public LoaderApp( Context context,String mUrl) {
super(context);
url = mUrl;
}
#Override
protected void onStartLoading() {
Log.v("forceload","force close dossseeeeeee!!!");
forceLoad();
}
#Override
public List<shelfs> loadInBackground(){
if(url==null){return null;}
Log.v("get books","get books");
List<shelfs> books = QueryUtils.fetchData(url);
Log.v("get query","get query");
Log.v("equals query","equals"+books.get(0)+""+books.get(2));
// books.add(new shelfs("books","books inback "));
return books;
}
the main Activity:
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<shelfs>> {
private shelfsAdapter adapter;
private static final String url = "https://www.googleapis.com/books/v1/volumes?q={search%20terms}";
private static final int ID=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//final String url1=" https://www.googleapis.com/books/v1/volumes?q=android&maxResults=1\n";
adapter = new shelfsAdapter(this, new ArrayList<shelfs>());
ListView listView = (ListView) findViewById(R.id.list);
Log.v("geturl fine","fine get it");
listView.setAdapter(adapter);
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// If there is a network connection, fetch data
if (networkInfo != null && networkInfo.isConnected()) {
// Get a reference to the LoaderManager, in order to interact with loaders.
android.app.LoaderManager loaderManager = getLoaderManager();
Log.v("loading ","loader inflater");
// Initialize the loader. Pass in the int ID constant defined above and pass in null for
// the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
// because this activity implements the LoaderCallbacks interface).
getSupportLoaderManager().initLoader(ID, null, this);
}}
#NonNull
#Override
public Loader<List<shelfs>> onCreateLoader(int id, #Nullable Bundle args) {
Log.v("get load","get load on create");
Toast.makeText(this,"creat it just!!!",Toast.LENGTH_SHORT).show();
adapter.add(new shelfs("oncreat","loadApp on create loader"));
return new LoaderApp(this,url);
}
#Override
public void onLoadFinished(#NonNull Loader<List<shelfs>> loader, List<shelfs> data) {
if(data != null && !data.isEmpty() )
Log.v("get load","get load on finished");
// adapter.add(new shelfs("onloadfinish","addall??"));
adapter.addAll(data);
adapter.notifyDataSetChanged();
// Log.v("data add","data"+data.get(0)+""+data.get(6));
// Toast.makeText(this,"data",Toast.LENGTH_SHORT).show();
}
#Override
public void onLoaderReset(#NonNull Loader<List<shelfs>> loader) {
Log.v("get load","get load on reset");
adapter.clear();
}
and the json class:
public class QueryUtils {
public QueryUtils(){}
public static List<shelfs> fetchData(String requestUrl) {
if (requestUrl ==null) {return null;}
Log.v("fetchData work!","fetchData work!");
URL uRl=getUrl(requestUrl);
Log.v("geturl work!","geturl work!");
String json=null;
try {
json=makeHttprequest(uRl);
Log.v("makehttp work!","makehttp work!");
}catch (IOException e){Log.v("error fetch","error fetch");}
List<shelfs> makeit=ExtractJsonData(json);
Log.v("extractdata work!","extractdata work!");
return makeit;
}
public static URL getUrl(String urlhttp) {
URL url=null;
try{ url=new URL(urlhttp);}
catch (MalformedURLException e){Log.v("url error","url error",e);}
return url;
}
public static String readStream(InputStream inputStream) throws IOException {
StringBuilder stringBuilder=new StringBuilder();
if(inputStream!=null)
{ InputStreamReader isr=new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader=new BufferedReader(isr);
String line=reader.readLine();
while(line!=null){stringBuilder.append(line);
line=reader.readLine();}}
return stringBuilder.toString();
}
public static String makeHttprequest(URL url)throws IOException{
String jsonResponse="";
InputStream inputStream=null;
HttpURLConnection urlConnection=null;
try {
urlConnection=(HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000);
urlConnection.setConnectTimeout(15000);
urlConnection.connect();
if(urlConnection.getResponseCode()==200)
{inputStream=urlConnection.getInputStream();
jsonResponse=readStream(inputStream);
Log.e("connect error","connect");}}
catch(IOException e){Log.e("connect error","connect error");}
finally{
if(urlConnection!=null){urlConnection.disconnect();}
if(inputStream!=null){inputStream.close();}
}
return jsonResponse; }
public static List<shelfs> ExtractJsonData(String jsonResponse){
List<shelfs> putshelfs=new ArrayList<>();
try {
JSONObject base=new JSONObject(jsonResponse);
JSONArray items=base.getJSONArray("items");
shelfs firstShelfs=new shelfs("","");
for(int i=0;i<items.length();i++)
{
JSONObject index = items.getJSONObject(i);
JSONObject volume=index.getJSONObject("volumeInfo");
String title=volume.getString("title");
JSONArray authors=volume.getJSONArray("authors");
String auth=authors.getString(0);
firstShelfs= new shelfs(title,auth);
putshelfs.add(i,firstShelfs);
Log.v("gggg","net get"+i+auth+title+"dom");}
Log.v("dff","json take");
} catch (JSONException e) {
e.printStackTrace(); }
return putshelfs;}
}
So I have a Recyclerview which holding items with images, I want to load images into the items but when I do that I got a lot of fps drops.
I read that I need to use another thread for the network part and I tried to do that as you can see, and it seems good to me but I can't figure out how to stop the fps drops and make the scrolling in the Recyclerview smooth, this Recyclerview supposed to hold between 10 and 100. Am I supposed to run the activity in a thread?
Note: The fps drops occur with 10 items.
calling to the HttpWrapper.LoadImageFromWebOperations function in OnBindViewHolder.
HomeAdapter.java
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.HomeViewHolder>{
private Context context;
private ArrayList<RecipeModel> items;
public HomeAdapter(Context context, ArrayList<RecipeModel> items) {
this.context = context;
this.items = items;
}
#Override
public HomeAdapter.HomeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.home_item,null);
HomeAdapter.HomeViewHolder holder = new HomeAdapter.HomeViewHolder(v);
return holder;
}
public void addItem(RecipeModel item){
this.items.add(item);
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(HomeAdapter.HomeViewHolder holder, final int position) {
RecipeModel model = items.get(position);
holder.name.setText(model.getName());
holder.directions.setText(model.getDirections()[0]);
Drawable drawable = HttpWrapper.LoadImageFromWebOperations(model.getImageSource());
holder.image.setImageDrawable(drawable);
}
#Override
public int getItemCount() {
return items.size();
}
class HomeViewHolder extends RecyclerView.ViewHolder{
TextView name;
TextView directions;
ImageView image;
public HomeViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.recipe_name);
directions = (TextView) itemView.findViewById(R.id.recipe_directions);
image = (ImageView) itemView.findViewById(R.id.recipe_image);
}
}
HttpWrapper.java
public class HttpWrapper {
String responseMsg = "";
private OkHttpClient client;
private Request request;
public static final String base_url = "http://kingtimmy.pythonanywhere.com";
public static final String home_route = "/home/";
public HttpWrapper() {
client = new OkHttpClient();
}
public ArrayList<RecipeModel> get_home_recipes(int recipe_num){
ArrayList<RecipeModel> models = new ArrayList<RecipeModel>();
request = new Request.Builder().url(base_url + home_route + String.valueOf(recipe_num)).build();
responseMsg = "";
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
responseMsg = "Error: " + e.getMessage();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
responseMsg = response.body().string();
}
});
while(responseMsg.equals("")){
continue;
}
String[] jsons = responseMsg.split("]-]");
for (int i = 0; i < jsons.length; i++){
models.add(makeRecipeModel(jsons[i]));
}
return models;
}
public RecipeModel makeRecipeModel(String msg){
JSONObject nodeRoot = null;
RecipeModel model;
try {
nodeRoot = new JSONObject(msg);
String[] directions = nodeRoot.get("directions").toString().split("\\n");
String[] ingredients = nodeRoot.get("ingredients").toString().split("\\n");
String image_source = nodeRoot.get("image").toString();
String source_url = nodeRoot.get("source_url").toString();
String name = nodeRoot.get("name").toString();
int id = Integer.valueOf(nodeRoot.get("id").toString());
model = new RecipeModel(directions,ingredients,image_source,source_url,name,id);
} catch (JSONException e) {
model = null;
}
return model;
}
public static Drawable LoadImageFromWebOperations(final String url) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Drawable> callable = new Callable<Drawable>() {
#Override
public Drawable call() {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
System.out.println("Exc=" + e);
return null;
}
}
};
Future<Drawable> future = executor.submit(callable);
// future.get() returns 2 or raises an exception if the thread dies, so safer
try {
Drawable d = future.get();
executor.shutdown();
return d;
} catch (Exception e) {
return null;
}
}
What am I doing wrong?
Instead of writing your own thread and code to fetch, parse, decode and load the image, give Glide a try. It does all that for you with a simple single line code and loads the image in your ImageView
I need to take the feeds of more RSS Feed urls that I have to aggregate and show the news in descending order.
Some links don't have an xml tag for <category> so I need to create one: I have to know where feeds come from so that I can categorize them.
This is what I'm trying to achieve: ( for Source n I mean the category)
[![enter image description here][1]][1]
I used to use Yahoo!Pipes to make all these changes.
My attempt was to create a CustomListView for each url and then execute the AsyncTasks all at once but that is not working correctly - the feeds are not displayed in ascending order.
MainActivity
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private RSSFeed myRssFeed = null;
String[] urlFeed = {"url1", "url2"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for (int i = 0; i < urlFeed.length; i++) {
News news = new News(i);
news.execute();
}
}
#Override
public void onRefresh() {
for (int i = 0; i < urlFeed.length; i++) {
News news = new News(i);
news.execute();
}
}
private class News extends AsyncTask<Object, Void, Void> {
protected int number;
public News(int urlNumber) {
number = urlNumber;
}
#Override
protected Void doInBackground(Object... arg0) {
String data = "";
InputStream iStream;
try{
URL url = new URL(urlFeed[number]);
// Creating an http connection to communicate with url
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuilder sbf = new StringBuilder();
String line;
while( ( line = br.readLine()) != null){
sbf.append(line);
}
data = sbf.toString();
br.close();
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler();
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(url.openStream());
myXMLReader.parse(myInputSource);
myRssFeed = myRSSHandler.getFeed();
} catch (ParserConfigurationException | IOException | SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (myRssFeed != null) {
NestedListView list = (NestedListView)findViewById(android.R.id.list);
list.setVisibility(View.VISIBLE);
CustomList adapter = new CustomList(MainActivity.this, myRssFeed.getList());
adapter.addAll();
list.setAdapter(adapter);
} else
Toast.makeText(MainActivity.this, "Error",
Toast.LENGTH_LONG).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
RSSFeed
public class RSSFeed {
private String title = null;
private String description = null;
private String link = null;
private String pubdate = null;
private String image = null;
private String enclosure = null;
private String author = null;
private List<RSSItem> itemList;
RSSFeed(){
itemList = new Vector<RSSItem>(0);
}
void addItem(RSSItem item){
itemList.add(item);
}
RSSItem getItem(int location){
return itemList.get(location);
}
List<RSSItem> getList(){
return itemList;
}
}
RSSItem
public class RSSItem {
private String title = null;
private String description = null;
private String link = null;
private String pubdate = null;
private String image = null;
private String enclosure = null;
private String author = null;
}
CustomList
public class CustomList extends ArrayAdapter<RSSItem> {
private static Activity context = null;
private final List<RSSItem> web;
public CustomList(Activity context, List<RSSItem> web) {
super(context, R.layout.new_listview, web);
CustomList.context = context;
this.web = web;
}
#SuppressLint("SetTextI18n")
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
#SuppressLint({"ViewHolder", "InflateParams"}) final View rowView = inflater.inflate(R.layout.new_listview, null, true);
ImageView imageView = (ImageView)rowView.findViewById(R.id.image);
Picasso.with(context).load(web.get(position).getImage()).into(imageView);
TextView textView = (TextView)rowView.findViewById(R.id.title);
textView.setText(Html.fromHtml(web.get(position).getTitle()));
TextView textView1 = (TextView)rowView.findViewById(R.id.description);
textView1.setText(web.get(position).getDescription());
TextView textView2 = (TextView)rowView.findViewById(R.id.pubdate);
textView2.setText(pubdate);
return rowView;
}
}
RSSHandler
public class RSSHandler extends DefaultHandler {
final int state_unknown = 0;
final int state_title = 1;
final int state_description = 2;
final int state_link = 3;
final int state_pubdate = 4;
final int state_enclosure = 6;
final int state_image = 5;
final int state_author = 7;
int currentState = state_unknown;
String url;
RSSFeed feed;
RSSItem item;
boolean itemFound = false;
RSSHandler(){
}
RSSFeed getFeed(){
return feed;
}
#Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
feed = new RSSFeed();
item = new RSSItem();
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("item")){
itemFound = true;
item = new RSSItem();
currentState = state_unknown;
}
else if (localName.equals("enclosure")) {
url = attributes.getValue("url");
currentState = state_image;
}
else if (localName.equalsIgnoreCase("title")){
currentState = state_title;
}
else if (localName.equalsIgnoreCase("description")){
currentState = state_description;
}
else if (localName.equalsIgnoreCase("link")){
currentState = state_link;
}
else if (localName.equalsIgnoreCase("pubdate")){
currentState = state_pubdate;
}
else if (localName.equalsIgnoreCase("author")){
currentState = state_author;
}
else{
currentState = state_unknown;
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (localName.equalsIgnoreCase("item")){
feed.addItem(item);
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String strCharacters = new String(ch,start,length);
if (itemFound){
// "item" tag found, it's item's parameter
switch(currentState){
case state_enclosure:
item.setEnclosure(strCharacters);
break;
case state_title:
item.setTitle(strCharacters);
break;
case state_image:
item.setImage(url);
break;
case state_description:
item.setDescription(strCharacters);
break;
case state_link:
item.setLink(strCharacters);
break;
case state_pubdate:
item.setPubdate(strCharacters);
break;
case state_author:
item.setAuthor(strCharacters);
break;
default:
break;
}
}
else{
// not "item" tag found, it's feed's parameter
switch(currentState){
case state_enclosure:
feed.setEnclosure(strCharacters);
break;
case state_title:
feed.setTitle(strCharacters);
break;
case state_image:
feed.setImage(url);
break;
case state_description:
feed.setDescription(strCharacters);
break;
case state_link:
feed.setLink(strCharacters);
break;
case state_pubdate:
feed.setPubdate(strCharacters);
break;
case state_author:
feed.setAuthor(strCharacters);
break;
default:
break;
}
}
currentState = state_unknown;
}
The solution requires more than one change. The first thing you need to do is make each News task that finishes adds its data to the one big list. That list can then be sorted which requires a Comparator.
You also need a list of the names to show in the placeholder youve called Source n in your image and lastly, so that you can compare them, you need to parse the dates as actual dates.
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private List<RSSItem> totalRssFeed = new ArrayList<>();
String[] urlFeed = {"MyURL", "MyUrl2", "MyUrl3"};
String[] names = {"Name", "Name2", "Name3"}
private CustomList adapter;
#Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ListView list = (ListView) findViewById(android.R.id.list);
adapter = new CustomList(MainActivity.this);
list.setAdapter( adapter );
}
#Override
protected void onResume() {
// do this here and you dont need to repeat it in refresh and create
for (int i = 0; i < urlFeed.length; i++) {
News news = new News(i);
news.execute();
}
}
public class CustomList extends ArrayAdapter<RSSItem> {
...
public CustomList(Activity context) { //dont start with default data
super(context, R.layout.new_listview, null);
}
...
}
private class News extends AsyncTask<Object, Void, Void> {
protected int number;
public News(int urlNumber) {
number = urlNumber;
}
#Override
protected Void doInBackground(Object... arg0) {
try {
//no need to do the input stuff you were doing before here?
URL url = new URL(urlFeed[number]);
SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
XMLReader myXMLReader = mySAXParser.getXMLReader();
RSSHandler myRSSHandler = new RSSHandler(names[number]);
myXMLReader.setContentHandler(myRSSHandler);
InputSource myInputSource = new InputSource(url.openStream());
myXMLReader.parse(myInputSource);
totalRssFeed.addAll(myRSSHandler.getFeed());
Collections.sort(totalRssFeed);
} catch (ParserConfigurationException | IOException | SAXException e) { /* stuff */ }
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.clear();
adapter.addAll(totalRssFeed);
}
}
public class RSSItem implements Comparable<RSSItem> {
public String tag;
public Date pubdate; //just public so i didnt need setters in this example
public RSSItem(String defaultTagToUse) {
//You should set the default to whatever you want displayed
//when the tag for <category> is missing, and just update it normally otherwise
tag = defaultTagToUse;
}
void setPubDate(Date date) {
pubdate = date;
}
...
#Override
public int compareTo(#NonNull RSSItem another) {
int res;
if (pubdate == null) {
if (another.pubdate == null) {
res = 0;
} else {
res = -1;
}
} else {
if (another.pubdate == null || pubdate.getTime() > another.pubdate.getTime()) {
res = 1;
} else {
res = -1;
}
}
return res;
}
}
public class RSSHandler extends DefaultHandler {
...
List<RSSItem> feed;
RSSItem item;
String mName;
public RssHandler(String name) {
mName = name;
}
List<RSSItem> getFeed() {
return feed;
}
#Override
public void startDocument() throws SAXException {
feed = new ArrayList<>();
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (localName.equalsIgnoreCase("item")) {
itemFound = true;
item = new RSSItem( name );
currentState = state_unknown;
} else ...
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("item")) {
feed.add(item);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
...
case state_pubdate:
SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); //make sure you match the format from your XML
item.setPubdate( formatter.parse(stringCharacters) );
break;
...
}
}
}
All the ...'s jsut mean leave everything as it was in those places
I am getting this error in this line of code in my class(Activity_B):
BreakingXmlPullParser.getStackSitesFromFile(**Activity_B.this**));
breakingSites = BreakingXmlPullParser.getStackSitesFromFile(
(**Activity_B.this**));
breakingSites = BreakingXmlPullParser.getStackSitesFromFile (Activity_B.this));
Here is the BreakingXmlPullParser Class
public class BreakingXmlPullParser {
static final String KEY_CONTENT = "Content";
static final String KEY_MAINHEADLINE = "MainHeadline";
static final String KEY_SUMMARYHEADLINE = "SummaryHeadline";
static final String KEY_EDITION = "Edition";
static final String KEY_IMAGE_URL = "Image";
static final String KEY_LOGO_URL = "Logo";
static final String KEY_STORY = "Story";
static final String KEY_AUTHOR = "Author";
static final String KEY_PUBLISHDATE = "PublishDate";
public static List<BreakingSite> getStackSitesFromFile(Context ctx) {
// List of StackSites that we will return
List<BreakingSite> breakingSites;
breakingSites = new ArrayList<>();
// temp holder for current BreakingSite while parsing
BreakingSite curBreakingSite = null;
// temp holder for current text value while parsing
String curText = "";
try {
// Get our factory and PullParser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
// Open up InputStream and Reader of our file.
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File(root.toString() + "/Android/data/"
+ "com.example.agispoc");
StringReader reader = new StringReader(getStringFromFile(dir+"/breakingnews.xml"));
Log.e("Responce", reader.toString());
XMLParser parser = new XMLParser();
Document doc = parser.getDomElement(getStringFromFile(dir+"/breakingnews.xml")); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_CONTENT);
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
Element e = (Element) nl.item(i);
curBreakingSite = new BreakingSite();
curBreakingSite.setMainheadline(parser.getValue(e, KEY_MAINHEADLINE));
curBreakingSite.setSummaryheadline(parser.getValue(e, KEY_SUMMARYHEADLINE));
curBreakingSite.setEdition(parser.getValue(e, KEY_EDITION));
curBreakingSite.setImgUrl(parser.getValue(e, KEY_IMAGE_URL));
curBreakingSite.setLogoUrl(parser.getValue(e, KEY_LOGO_URL));
curBreakingSite.setStory(parser.getValue(e, KEY_STORY));
curBreakingSite.setAuthor(parser.getValue(e, KEY_AUTHOR));
curBreakingSite.setPublishdate(parser.getValue(e, KEY_PUBLISHDATE));
breakingSites.add(curBreakingSite);
Log.e("Response", breakingSites.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
// return the populated list.
return breakingSites;
}
public static String convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
return sb.toString();
}
public static String getStringFromFile (String filePath) throws Exception {
File fl = new File(filePath);
FileInputStream fin = new FileInputStream(fl);
String ret = convertStreamToString(fin);
//Make sure you close all streams.
fin.close();
return ret;
}
}
And here is Activity_B
public class Activity_B extends android.support.v4.app.Fragment {
private InterstitialAd interstitial;
private BreakingSiteAdapter mAdapter;
private ListView sitesList;
private Toolbar mToolbar;
private SwipeRefreshLayout mSwipeRefreshLayout = null;
static final String KEY_CONTENT = "Content";
static final String KEY_MAINHEADLINE = "MainHeadline";
static final String KEY_SUMMARYHEADLINE = "SummaryHeadline";
static final String KEY_EDITION = "Edition";
static final String KEY_IMAGE_URL = "ImgUrl";
static final String KEY_LOGO_URL = "Logo";
static final String KEY_STORY = "Story";
static final String KEY_AUTHOR = "Author";
static final String KEY_PUBLISHDATE = "PublishDate";
List<BreakingSite> breakingSites;
ProgressDialog mProgressDialog;
FragmentManager mFragmentManager;
FragmentTransaction mFragmentTransaction;
private LinearLayout x;
private FragmentActivity fa;
//private Context cm;
private static Context ctx;
//private Context mContext;
#Override
public void onAttach(final Activity Activity_B) {
super.onAttach(Activity_B);
ctx = Activity_B;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fa = super.getActivity();
// x = (LinearLayout) inflater.inflate(R.layout.b, container, false);
View x = inflater.inflate(R.layout.b,null);
Context context = getActivity();
mSwipeRefreshLayout = (SwipeRefreshLayout)x.findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new SitesDownloadTask().execute();
}
});
Log.i("StackSites", "OnCreate()");
mProgressDialog = new ProgressDialog(getActivity());
sitesList = (ListView)x.findViewById(R.id.list);
sitesList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int pos,
long id) {
Intent in = new Intent(getContext(),
Bpage1.class);
in.putExtra(KEY_MAINHEADLINE, breakingSites.get(pos).getMainheadline());
in.putExtra(KEY_STORY, breakingSites.get(pos).getStory());
in.putExtra(KEY_LOGO_URL, breakingSites.get(pos).getLogoUrl());
in.putExtra(KEY_IMAGE_URL, breakingSites.get(pos).getImgUrl());
in.putExtra(KEY_AUTHOR, breakingSites.get(pos).getAuthor());
in.putExtra(KEY_PUBLISHDATE, breakingSites.get(pos).getPublishdate());
//in.putExtra(KEY_IMAGE_URL, breakingSites.get(pos).getImgUrl());
startActivity(in);
}
});
if (isNetworkAvailable()) {
Log.i("StackSites", "starting download Task");
SitesDownloadTask download = new SitesDownloadTask();
download.execute();
} else {
mAdapter = new BreakingSiteAdapter(Activity_B.this, -1,
BreakingXmlPullParser.getStackSitesFromFile(Activity_B.this));
sitesList.setAdapter(mAdapter);
}
return x;
}
public void displayInterstitial() {
if (interstitial.isLoaded()) {
interstitial.show();
}
}
private boolean isNetworkAvailable() {
ConnectivityManager conManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conManager.getActiveNetworkInfo();
return ( netInfo != null && netInfo.isConnected() );
}
private class SitesDownloadTask extends AsyncTask<Void, Void, Void> {
String xml;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
mProgressDialog.setTitle(getString(R.string.app_name));
mProgressDialog.setMessage("Loading...Please wait a moment...");
mProgressDialog.setCancelable(true);
mProgressDialog.setIcon(R.drawable.ic_launcher);
mProgressDialog.show();
mSwipeRefreshLayout.setRefreshing(false);
}
#Override
protected Void doInBackground(Void... arg0) {
BreakingDownloader
.DownloadFromUrl("http://nte.nmh.com.na/MyInfo/Master/Category/breakingnews.xml");
return null;
}
#Override
protected void onPostExecute(Void result) {
// setup our Adapter and set it to the ListView.
mProgressDialog.dismiss();
breakingSites = BreakingXmlPullParser.getStackSitesFromFile(
(Activity_B.this));
breakingSites = BreakingXmlPullParser.getStackSitesFromFile (Activity_B.this));
sitesList.setAdapter(mAdapter);
Log.i("StackSites", "adapter size = " + mAdapter.getCount());
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
// finish();
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Please assist me.The aim of this appliaction is to display the listview inside fragment.I had to convert an entire activity into a fragment,and so far i am new to fragments.
Please help me solve the context issue.I dont understand why the activity_B fragment cannot recognize the context ctx in BreakingXmpPullParser.Please dont vote me down.I am new and just trying to learn here...
error screenshot
Error screenshot2
The reason is your Activity_B extends Fragment and not Activity, just pass getActivity() to your function instead of Activity_B.this
like this
BreakingXmlPullParser.getStackSitesFromFile(getActivity()));
just replace wherever you need context you pass in getActivity() and not Acitivty_B.this remember Activity_B is not an activity anymore but a fragment !
Im trying to code an android RSS reader that will (for now) parse the xml from this MangaPanda List. I'm using this Android XML example for basic structure (and because it uses XMLPullParser) as well as this example because of its clear explanation of its EfficientAdapter, AsyncTask, and ListView usage.
So far I think I've "merged" the two pretty well but I cant quite figure out how to properly execute the parsing process.
My question is: How would I properly implement the LoadXmlFromNetwork() so that it would return the proper format for my adapter?
MainActivity:
//Implementation of AsyncTask used to download XML feed from stackoverflow.com.
private class loadingTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
try {
return loadXmlFromNetwork(urls[0]);
} catch (IOException e) {
return getResources().getString(R.string.hello_world);
} catch (XmlPullParserException e) {
return getResources().getString(R.string.menu_settings);
}
}
#Override
protected void onPostExecute(String result) {
setContentView(R.layout.activity_main);
// Displays the HTML string in the UI via a WebView
listview1.setAdapter(new EfficientAdapter(MainActivity.this, Manga));
ShowProgress.dismiss();
}
}
public Manga loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
InputStream stream = null;
// Instantiate the parser
MainParser MainParser = new MainParser();
List<Manga> mangas = null;
String mangaAlpha = null;
String mangaName = null;
boolean mangaComplete = false;
try {
stream = downloadUrl(urlString);
mangas = MainParser.parse(stream);
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (stream != null) {
stream.close();
}
}
// StackOverflowXmlParser returns a List (called "entries") of Entry objects.
// Each Entry object represents a single post in the XML feed.
// This section processes the entries list to combine each entry with HTML markup.
// Each entry is displayed in the UI as a link that optionally includes
// a text summary.
return mangas;
}
// Given a string representation of a URL, sets up a connection and gets
// an 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 the query
conn.connect();
InputStream stream = conn.getInputStream();
return stream;
}
}
MainParser:
public class MainParser {
// We don't use namespaces
private static final String ns = null;
public List<Manga> parse(InputStream in) throws XmlPullParserException, IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(in, null);
parser.nextTag();
return readFeed(parser);
} finally {
in.close();
}
}
private List<Manga> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
List<Manga> mangas = new ArrayList<Manga>();
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the entry tag
if (name.equals("li")) {
mangas.add(readTag(parser));
} else {
skip(parser);
}
}
return mangas;
}
private Manga readTag(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, "li");
String mangaAlpha =null;
String mangaName = null;
String mangaLink = null;
boolean mangaComplete = false;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("a")) {
mangaAlpha = parser.getAttributeValue(null, "name");
} else if (name.equals("a")) {
mangaName = parser.getText();
} else if (name.equals("a")) {
mangaLink = parser.getAttributeValue(null, "href");
} else if (name.equals("span")) {
mangaComplete = true;
} else {
skip(parser);
}
}
return new Manga(mangaAlpha, mangaName, mangaLink, mangaComplete);
}
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}
My EfficientAdapter:
public class EfficientAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<Manga> mangadata;
private static LayoutInflater inflater = null;
//public ImageLoader imageLoader;
ViewHolder holder;
EfficientAdapter(Activity a, ArrayList<Manga> d) {
activity = a;
mangadata = d;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//imageLoader = new ImageLoader(activity.getApplicationContext());
}
#Override
public int getCount() {
return mangadata.toArray().length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder {
public TextView label;
public TextView addr;
//public ImageView image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null) {
vi = inflater.inflate(R.layout.textholder, null);
holder = new ViewHolder();
holder.label = (TextView) vi.findViewById(R.id.textView1);
holder.addr = (TextView) vi.findViewById(R.id.textView2);
//holder.image = (ImageView) vi.findViewById(R.id.icon);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
holder.label.setText(mangadata.get(position).getMangaAlpha());
holder.addr.setText(mangadata.get(position).getMangaName());
//imageLoader.DisplayImage((data.get(position).getThumbnail()), activity,
// holder.image, 72, 72);
return vi;
}
}
On a side note: I didn't know how much of my code would be necessary to properly explain my problem so please feel free to edit out unnecessary parts.
Change your asynctask like that:
private class loadingTask extends AsyncTask<String, Void, List<Manga>> {
#Override
protected String doInBackground(String... urls) {
try {
return loadXmlFromNetwork(urls[0]);
} catch (IOException e) {
return null;
} catch (XmlPullParserException e) {
return null;
}
}
#Override
protected void onPostExecute(List<Manga> result) {
setContentView(R.layout.activity_main);
// Displays the HTML string in the UI via a WebView
listview1.setAdapter(new EfficientAdapter(MainActivity.this, result));
ShowProgress.dismiss();
}
}
public List<Manga> loadXmlFromNetwork(String urlString) throws XmlPullParserException, IOException {
....