I've got a couple RSS feeds I need to parse for my app and I followed the excellent tutorial here: http://w2davids.wordpress.com/android-rssatom-feeds-parsing-with-rome/. I modified the sample a bit and got it to do what I needed. So, I went to integrate it into my app and consistently get a Force Quit every time I try to display the list of posts. My modified version of the code is below. It always seems to fail when attaching the adapter to the ListView, so I assume my adapter is setup incorrectly. What's strange us that in the debugger, I can look at the adapter and see the data I'm trying to fetch.
Thanks in advance:
public class View1 extends Activity
{
/** Called when the activity is first created. */
private final ArrayList<String> list = new ArrayList<String>();
private ListView listView;
private ArrayAdapter<String> adapter = null;
private SyndContent desc;
private ArrayList<String> d = new ArrayList<String>() ;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
adapter = new ArrayAdapter<String>(this, R.layout.dataview, R.id.ListItemView);
getRSS("http://www.example.com/wp/?feed=gigpress&artist=1");
listView.setAdapter(adapter);
listView = (ListView) this.findViewById(R.id.ListView);
listView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long duration)
{
Intent intent = new Intent();
intent.setClassName("com.example.idtb", "com.example.idtb.ViewRssDescription");
intent.putExtra("desc", d.get(position));
startActivity(intent);
}
});
}
private void getRSS(String rss)
{
URL feedUrl;
try
{
Log.d("DEBUG", "Entered:" + rss);
feedUrl = new URL(rss);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(feedUrl));
List entries = feed.getEntries();
Iterator iterator = entries.listIterator();
while (iterator.hasNext())
{
SyndEntry ent = (SyndEntry) iterator.next();
String title = ent.getTitle();
desc = ent.getDescription();
d.add(desc.getValue());
adapter.add(title);
}
adapter.notifyDataSetChanged();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (FeedException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
I think adapter should look something like this:
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, lst);
Related
I am working on an android application. In this application, I have to retrieve data from a web service and put it in a listview, but it is not retrieving anything. I don't know what I am doing wrong here. Maybe someone can help me with this.
Webservice: http://10.247.240.53/kas/lampen.php
Mainactivity:
`
public class MainActivity extends AppCompatActivity {
ListView listView;
ArrayAdapter<String> adapter;
String[] data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
getData();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, Showdata.class);
intent.putExtra("teeltbed", listView.getItemAtPosition(position).toString());
startActivity(intent);
}
});
}
private void getData()
{
String getData = null;
String dbResult = "empty";
dbConnect database = new dbConnect(this);
try{
String query = "SELECT * FROM Lamp";
getData = "?query=" + URLEncoder.encode(query, "UTF-8");
String link = "http://10.247.240.53/kas/lampen.php";
dbResult = database.execute(link).get();
}
catch (Exception e){
}
try{
JSONArray ja = new JSONArray(dbResult);
JSONObject jo = null;
data = new String[ja.length()];
for (int i = 0; i < ja.length(); i++)
{
jo = ja.getJSONObject(i);
data[i] = jo.getString("teeltbed");
}
adapter = new ArrayAdapter<String>(this, R.layout.layout_list, R.id.list_item, data);
listView.setAdapter(adapter);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}`
Im using volley to download the JSON data from a server, setting the Adapter within the function that reads and parses the data. However, the adapter is not being recognized. The problem is, I have successfully implemented the adapter in another activity with the same method without errors. The following is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras!=null) {
user_id = getIntent().getStringExtra("user_id");
} else {
Intent logIn = new Intent(JoinedActivity.this, LoginActivity.class);
startActivity(logIn);
}
setContentView(R.layout.activity_joined);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView1);
recyclerView.addItemDecoration(new SimpleDividerItemDecoration(this));
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
GetJoinedEvents();
}
public void GetJoinedEvents(){
String tag_string_req = "req_getJoinedEvents";
StringRequest stringRequest = new StringRequest(Request.Method.GET, Config.URL_USER_lIST_EVENTS+user_id, new Response.Listener<String>(){
#Override
public void onResponse(String response) {
// progressDialog.dismiss();
Log.i("responseTest",response);
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray result = jsonObject.getJSONArray(Config.TAG_JSON_ARRAY);
int length = result.length();
HashMap<String, String> events;
for (int i = 0; i < length; i++) {
JSONObject jo = result.getJSONObject(i);
String event_id = jo.getString(Config.TAG_EVENT_ID);
String name = jo.getString(Config.TAG_EVENT_NAME);
String date = jo.getString(Config.TAG_EVENT_START_DT);
String weekday = jo.getString(Config.TAG_EVENT_WEEKDAY);
String event_type = jo.getString(Config.TAG_EVENT_TYPE);
events = new HashMap<>();
events.put(Config.TAG_EVENT_ID, event_id);
events.put(Config.TAG_EVENT_NAME, name);
events.put(Config.TAG_EVENT_START_DT, date);
events.put(Config.TAG_EVENT_WEEKDAY, weekday);
events.put(Config.TAG_EVENT_TYPE, event_type);
eventList.add(events);
}
listAdapter = new RecyclerViewAdapter(JoinedActivity.this,eventList, user_id);
recyclerView.setAdapter(listAdapter);
}
catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", "Bad internet connection");
}
}) {};
AppController.getInstance().addToRequestQueue(stringRequest, tag_string_req);
Log.i("URL", stringRequest.toString());
}
}
A better approach to this is just to initialize the Recycler view and adapter on the onCreate. Then later on when you have the data you could create a swapItems method just for the purpose of changing the data within the recyclerview through the adapter, but in a way that both the RecyclerView and its adapter is instantiated as the activity starts.
on your swapItems you could do something like below:
public void swapItems(List<Events> eventList) {
if (eventList != null) {
this.items = eventList;
notifyDataSetChanged();// should call this to let the recyclerview know that our data set has changed
}
}
Then you could just call it via the activity by
listAdapter.swapItems(eventList);// this is done the moment you already got your list of events
I'm trying to populate an ArrayList of objects and use those objects to populate a ListView. My Asynctask can get the json data and I can parse it and make the objects I need but my ListView doesn't populate. When I check to see if my ArrayList has any object in it before the adapter runs I can see that it doesn't. I want to know why my ListView isn't populating.
Here's my code: (Sorry if it's messy, some spots I haven't gotten to updating yet)
public class MovieDisplayFragment extends Fragment{
private ArrayList<Movie> movieList = new ArrayList<Movie>();
private MovieAdapter movieAdapter;
ListView listView;
public MovieDisplayFragment(){
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
movieAdapter = new MovieAdapter(getActivity(), movieList);
listView = (ListView) rootView.findViewById(R.id.listview_data);
listView.setAdapter(movieAdapter);
if(movieList.size() > 0) {
Log.e("Hello", "1");
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l){
Movie movie = movieAdapter.getItem(position);
Intent i = new Intent(getActivity(), DetailActivity.class)
.putExtra(Intent.EXTRA_TEXT, "Hello");
startActivity(i);
}
});
return rootView;
}
private void updateMovieData(){
getMovieData movieData = new getMovieData();
movieData.execute();
}
#Override
public void onStart(){
super.onStart();
updateMovieData();
}
public class getMovieData extends AsyncTask<Void, Void, List<Movie>> {
private final String LOG_CAT = getMovieData.class.getSimpleName();
private List<Movie> getMovieData(String movieJsonStr) throws JSONException {
final String MOV_ITEMS = "results";
final String MOV_TITLE = "original_title";
final String MOV_DATE = "release_date";
final String MOV_SYNOPSIS = "overview";
final String MOV_VOTE = "vote_average";
final String MOV_POSTER_URL = "poster_path";
JSONObject movieJson = new JSONObject(movieJsonStr);
JSONArray movieArray = movieJson.getJSONArray(MOV_ITEMS);
Log.e("Hello", "2");
for (int i = 0; i < movieArray.length(); i++) {
JSONObject movie = movieArray.getJSONObject(i);
movieList.add(new Movie(movie.getString(MOV_TITLE), movie.getString(MOV_DATE),
movie.getString(MOV_SYNOPSIS), movie.getString(MOV_VOTE), movie.getString(MOV_POSTER_URL)));
}
return movieList;
}
protected List<Movie> doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String movieJsonStr = null;
try {
final String BASE_URL = "http://api.themoviedb.org/3/genre/10751/movies?api_key=358f3b44734f7e6404f2d01a62d3c176&include_all_movies=true&include_adult=true";
Uri builtUri = Uri.parse(BASE_URL).buildUpon().build();
URL url = new URL(builtUri.toString());
Log.v(LOG_CAT, "Built URI " + builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null){
movieJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while((line = reader.readLine()) != null){
buffer.append(line + "\n");
}
if (buffer.length() == 0){
movieJsonStr = buffer.toString();
}
movieJsonStr = buffer.toString();
Log.v(LOG_CAT, "Movie String: " + movieJsonStr);
} catch (IOException e) {
Log.e("Fragment", "Error", e);
movieJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
try {
return getMovieData(movieJsonStr);
} catch (JSONException e) {
Log.e(LOG_CAT, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<Movie> movies){
if(movies != null){
movieAdapter.clear();
for(Movie movieData : movies){
movieAdapter.add(movieData);
}
}
}
}
}
Put these 2 lines inside your onPostExecute() in Async.
movieAdapter = new MovieAdapter(getActivity(), movieList);
listView.setAdapter(movieAdapter);
AsyncTask runs in Background Thread. It gets the data from json after few seconds. But your adapter is called few milli seconds after your fragment is created.
So the data from the Json will not be there when you are setting the adapter.
Calling it in onPostExecute solves this problem as the adatpter is set after Json data is retrieved from the server!
Hope it helps a bit.
You are printing size of movieList (movieList.size()) much before movieList() is getting populated. It will never print "Hello" "1" in debugger. The asynctask will fill data in movieList much later than your movieList.size() check code in OnCreateView()
Anyways, after the below code
for(Movie movieData : movies)
{
movieAdapter.add(movieData);
}
you need to insert this bit:
listView.setAdapter(movieAdapter);
You are populating the adapter but not setting it to your listView in your onPostExecute() in your getMovieData Asynctask.
It looks like on post execute you are clearing the List that your adapter is using to populate the listview, then adding in new items to the list. However, in order to update the view after that happens, you need to call notifyDataSetChanged(); after updating the list
#Override
protected void onPostExecute(List<Movie> movies){
if(movies != null){
movieAdapter.clear();
for(Movie movieData : movies){
movieAdapter.add(movieData);
}
movieAdapter.notifyDataSetChanged();
}
}
I'm trying to create a window which will display a listbox populated with an array parsed from JSON.
The listview is populated and created in the OnCreate method in my MainActivity. In the main activity I'm also calling an AsyncTask to parse the JSON array from a website.
The task is shown below:
public class JSONParse extends AsyncTask<String, String, String[]> {
#Override
protected String[] doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream IStream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(IStream));
StringBuffer buffer = new StringBuffer();
String recievedLine = "";
while ((recievedLine = reader.readLine()) != null) {
buffer.append(recievedLine);
}
String full = buffer.toString();
JSONObject JSONParent = new JSONObject(full);
JSONArray j_Puzzles = JSONParent.getJSONArray("PuzzleIndex");
int arraySize = j_Puzzles.length();
String[] s_Puzzles = new String[arraySize];
StringBuffer endString = new StringBuffer();
for (int i = 0; i < j_Puzzles.length(); i++) {
s_Puzzles[i] = j_Puzzles.toString(i);
endString.append(s_Puzzles[i] + "\n");
}
MainActivity.Waiting = true;
return s_Puzzles;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
What is the best way to get s_Puzzles out of the background thread and into my OnCreate so it can be used like this:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new JSONParse().execute("http://www.hull.ac.uk/php/349628/08309/acw/index.json");
ListView listView = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, s_Puzzles);
listView.setAdapter(arrayAdapter);
}
}
Furthermore, am I going to have to pause the OnCreate method until the background worker is done in order to prevent the listview updating with nothing due to the worker thread not finishing.
Any help appreciated. Thanks
You are trying to call the AsyncTask and then you are setting the information when you are not certain that the information is loaded. Remember that it is being loaded Asynchronously. I recommend you to do that on the onPostExecute() method of the AsyncTask.
An AsyncTask has 4 methods that you can customize:
doInProgress: Send from the thread to the UI thread (Activity) the progress, normally a number. Here you can update the UI.
onPreExecute: To setup things before the thread starts running. Here you can update the UI.
doInBackground: You already have it, it's perfect. Here you cannot update the UI because this one runs on the background thread. It's the only method from the AsyncTask that doesn't run on the UI Thread (Activity).
onPostExecute: You get the result from the doInBackground. Here is where you should update your UI.
You can find any tutorial for AsyncTask and its easy. In this project I use an AsyncTask for kind of the same.
https://github.com/isaacurbina/ViewHolderListView/tree/master/app/src/main/java/com/mac/isaac/viewholderlistview
Hope it helps!
Something like this will work, without the need to overcomplicate what you already have:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ListView listView = (ListView) findViewById(R.id.listView);
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, new ArrayList<String>());
listView.setAdapter(arrayAdapter);
new JSONParse() {
#Override
protected void onPostExecute(String[] puzzles)
{
super.onPostExecute(puzzles);
arrayAdapter.addAll(puzzles);
}
}.execute("http://www.hull.ac.uk/php/349628/08309/acw/index.json");
}
I've been searching on here but can't seem to find what works. I'm trying to write a simple object list to a serialized file and can't seem to locate the file in android. It's my first time building an app and I had this working in netbeans by pointing to src/list.ser, however, this doesn't work in android studio. I guess my question is where do I place the ser file and how do I point to it in the code? Here is my code:
ListActivity:
public class ListActivity extends Activity implements Serializable {
private ArrayList<Item> list;
public List() throws Exception {
list = new ArrayList<Item>();
}
public void addItem(String name) {
list.add(new Item(name));
}
public void addCurrentList() throws Exception{
String pathToAppFolder = getExternalFilesDir(null).getAbsolutePath();
String filePath = pathToAppFolder +File.separator + "list.ser";
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
os.writeObject(list);
os.close();
}
catch (Exception e) {
System.out.println("NOPE NOPE NOPE NOPE");
}
}
public void addItem(String name, int price) {
list.add(new Item(name, price));
}
public ArrayList<Item> populate() {
return list;
}
public void record() {
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("src/list.ser"));
ArrayList<Item> list2 = (ArrayList<Item>) in.readObject();
System.out.println(list2);
list = list2;
in.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
private List tester;
private ListView lv;
private EditText gg;
private Button button;
private Button clearButton;
private ArrayList list;
String pathToAppFolder = getExternalFilesDir(null).getAbsolutePath();
String filePath = pathToAppFolder + File.separator + "list.ser";
#Override
protected void onDestroy() {
try {
tester.addCurrentList();
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//create the list
lv = (ListView) findViewById(R.id.listDisplay);
ListView mine = lv;
list = new ArrayList<String>();
try {
tester = new List();
}
catch (Exception e) {
}
for (Item item : tester.populate()) {
list.add(item);
}
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,list);
lv.setAdapter(arrayAdapter);
final TextView firstTextView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
clearButton = (Button) findViewById(R.id.clear);
gg = (EditText) findViewById(R.id.item);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String no = gg.getText().toString();
if (!no.isEmpty()) {
tester.addItem(no);
arrayAdapter.add(no);
arrayAdapter.notifyDataSetChanged();
gg.setText("");
}
}
});
clearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
arrayAdapter.clear();
arrayAdapter.notifyDataSetChanged();
}
});
lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = lv.getItemAtPosition(position).toString();
arrayAdapter.remove(arrayAdapter.getItem(position));
arrayAdapter.notifyDataSetChanged();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
First of all make sure that you have permission to write to the external storage.
as,
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
You can use,
public void addCurrentList() throws Exception{
String pathToAppFolder = getExternalFilesDir(null).getAbsolutePath();
String filePath = pathToAppFolder +File.seperator + "list.ser";
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
os.writeObject(list);
os.close();
}
catch (Exception e) {
System.out.println("");
}
}
and the use create a file path from that as,
String filePath = pathToAppFolder +File.seperator + "Test.text";
and then where ever you want to read this file again, you can recreate the path. Because you have access to the context from the android code
EDIT
You can not access the context as you do in your code. You can do it in your onCreate method. I have added only the necessary parts.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pathToAppFolder = getExternalFilesDir(null).getAbsolutePath();
filePath = pathToAppFolder + File.separator + "list.ser";
//create the list
Oh my god, I had to go into great lengths to answer your question. Here it is, Your List class is not an Activity in your application. It is just a class. So I suggest you to remove those inheritance first. remove this extends Activity. And I suggest you to change the List class name to something else. Because, List is a defined keyword and its not a best practice to do so.
Change the method in List Activity as below.
public void addCurrentList(String filePath) throws Exception
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath));
os.writeObject(list);
os.close();
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void record(String filePath) {
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath));
ArrayList<Item> list2 = (ArrayList<Item>) in.readObject();
System.out.println(list2);
list = list2;
in.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
In your MainActivity, onDestroy Method,
change the code to,
tester.addCurrentList(filePath);