Adding parsed JSON to a ListView and displaying it - android

public class GithubTab extends Fragment implements AdapterView.OnItemClickListener {
ListView repoListView;
private ListAdapter adapter;
private List<RepositoryItem> repoListItems;
private List<String> repoNameList;
private List<String> userNameList;
private List<String> descriptionList;
private TextView tvData;
private static final String TAG = "Github Tab";
Button buttonHit;
TextView resultText;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.github_tab, container, false);
repoListView = (ListView) view.findViewById(R.id.repoList);
repoListItems = new ArrayList<>();
repoNameList = new ArrayList<>();
userNameList = new ArrayList<>();
descriptionList = new ArrayList<>();
adapter = new ListAdapter(getContext(), repoListItems);
repoListView.setAdapter(adapter);
tvData = (TextView) view.findViewById(R.id.tvJsonItem);
// Clickable: able to open the GitHub webpage of the re
repoListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getContext(), "Clicked id" + view.getTag(), Toast.LENGTH_SHORT).show();
}
});
new JSONTask().execute("https://api.github.com/users/whyjay17/repos");
for(int i = 0; i < repoNameList.size(); i++) {
repoListItems.add(new RepositoryItem(i, repoNameList.get(i), userNameList.get(i), "ddd"));
}
return view;
}
public class JSONTask extends AsyncTask<String, String, String> {
#Override
// Any non-UI thread process is running in this method. After completion, it sends the result to OnPostExecute
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
.... Code Hidden ....
return retreivedJson;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//cant close null
if (connection != null) {
// close both connection and the reader
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public void formatJSONArray(String results){
try {
JSONArray jsonArray = new JSONArray(results);
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
if(jsonObject.optString("name") != null) {
//tvData.append(jsonObject.getString("name"));
repoNameList.add(jsonObject.getString("name"));
//Toast.makeText(getContext(), "1 " + repoNameList.get(1), Toast.LENGTH_SHORT).show();
}
if(jsonObject.optJSONObject("owner") != null){
JSONObject ownerObject=jsonObject.getJSONObject("owner");
if(ownerObject.optString("login")!=null) {
//tvData.append(ownerObject.getString("login"));
userNameList.add(ownerObject.getString("login"));
//ownerObject.append(ownerObject.getString("avatar_url"));
}
}
}
}catch (JSONException jsonException){
}
}
/*
* Called after the background computation finishes. Result of doInBackground is passed in as a parameter.
*
* */
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
/* for JSONArray data*/
if(result!=null && !result.isEmpty()) {
formatJSONArray(result);
}
}
}
}
The code above basically tries to parse a JSON data from https://api.github.com/users/famous/repos, adds some certain info (repo name, id, description) to the corresponding lists, and tries to display that on the listView that I created.
The listView works when I hard code the information (meaning that there is no problem with the listView itself), but when I try to put in the data inside the list (which has the parsed JSON info and I tested that it is actually inside the list), it gives me an empty list.
How can I make this work?

The data come asynchronous so inside onCreateView() the list data may not be ready yet for adding to adapter.
You need to move the code that add elements to ListView adapter into onPostExecute(), after formatJSONArray() method, then call notifyDatasetChange() to invalidate the ListView
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
/* for JSONArray data*/
if(result!=null && !result.isEmpty()) {
formatJSONArray(result);
for(int i = 0; i < repoNameList.size(); i++) {
repoListItems.add(new RepositoryItem(i,
repoNameList.get(i), userNameList.get(i), "ddd"));
}
adapter.notifyDatasetChanged();
}
}

You can call adapter.notifiDatasetchange() in your formatJSONArray method:
public void formatJSONArray(String results){
try {
JSONArray jsonArray = new JSONArray(results);
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
if(jsonObject.optString("name") != null) {
//tvData.append(jsonObject.getString("name"));
repoNameList.add(jsonObject.getString("name"));
//Toast.makeText(getContext(), "1 " + repoNameList.get(1), Toast.LENGTH_SHORT).show();
}
if(jsonObject.optJSONObject("owner") != null){
JSONObject ownerObject=jsonObject.getJSONObject("owner");
if(ownerObject.optString("login")!=null) {
//tvData.append(ownerObject.getString("login"));
userNameList.add(ownerObject.getString("login"));
//ownerObject.append(ownerObject.getString("avatar_url"));
}
}
}
adapter.notifiDatasetchange();
}catch (JSONException jsonException){
}
}
If it don't work , you can set adapter again in your formatJSONArray method
adapter = new ListAdapter(getContext(), repoListItems);
repoListView.setAdapter(adapter);
It worked for me. I hope it can help your problem!

for(int i = 0; i < repoNameList.size(); i++) {
repoListItems.add(new RepositoryItem(i,repoNameList.get(i),userNameList.get(i), "ddd"));
}
adapter.notifyDataSetChanged();
`
add this line before
}catch (JSONException jsonException){

Related

Android: How to add AsyncTaskLoader to this RecyclerView

[Update] Added repository link to download the project
I'm having this activity which connects to a URL to fetch data and display it using RecyclerView with a custom adapter. How can I edit this code to use AsyncTaskLoader instead of AsyncTask? here's the repository to download the very simple project Soonami tutorial app
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
public static QuakesAdapter quakesAdapter;
public static ArrayList<Event> eventsList = new ArrayList<>();
public static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
quakesAdapter = new QuakesAdapter(this, eventsList);
//defining recyclerView and setting the adapter
quakesAdapter.notifyDataSetChanged();
FetchData fetchData= new FetchData();
fetchData.execute();
}
private class FetchData extends AsyncTask<String, Void, ArrayList<Event>> {
String myDdata = "";
String line = "";
#Override
protected ArrayList<Event> doInBackground(String... params) {
try {
//opening the connection
if (httpURLConnection.getResponseCode() == 200) {
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while(line != null){
line = bufferedReader.readLine();
myDdata = myDdata + line;
}
JSONObject jsonObject = new JSONObject(myDdata);
eventsList.clear();
JSONArray jsonArray = jsonObject.getJSONArray("features");
for(int i = 0; i < jsonArray.length(); i++){
//getting values of the 3 attributes
eventsList.add(new Event(title, time, tsunamiAlert));
}
if (inputStream != null) {
inputStream.close();
}
} else {
Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<Event> result) {
super.onPostExecute(result);
quakesAdapter.notifyDataSetChanged();
}
}
}
I have tested multiple examples but they have different codes and triggers multiple errors with my code like this one and still looking for a solution which makes my code works fine.
Set adpter in your recyclerview and then call the loader like this way:
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Event>> {
{
private RecyclerView recyclerView;
public static QuakesAdapter quakesAdapter;
public static ArrayList<Event> eventsList = new ArrayList<>();
public static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";
#Override
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
quakesAdapter = new QuakesAdapter(this, eventsList);
//defining recyclerView and setting the adapter
recyclerView.setAdapter(quakesAdapter);
getSupportLoaderManager().initLoader(1, null, this).forceLoad();
}
#Override
public Loader<List<Event>> onCreateLoader ( int id, Bundle args){
return new FetchData(MainActivity.this);
}
#Override
public void onLoadFinished (Loader < List < Event >> loader, List < Event > data){
quakesAdapter.setData(data);
}
#Override
public void onLoaderReset (Loader < List < Event >> loader) {
quakesAdapter.setData(new ArrayList<Event>());
}
Performs actual task in background and returns the result.
private static class FetchData extends AsyncTaskLoader<List<Event>>{
String myDdata = "";
String line = "";
public FetchData(Context context) {
super(context);
}
#Override
public List<Event> loadInBackground () {
try {
List<Event> list = new ArrayList<Event>();
//opening the connection
if (httpURLConnection.getResponseCode() == 200) {
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while (line != null) {
line = bufferedReader.readLine();
myDdata = myDdata + line;
}
JSONObject jsonObject = new JSONObject(myDdata);
JSONArray jsonArray = jsonObject.getJSONArray("features");
for (int i = 0; i < jsonArray.length(); i++) {
//getting values of the 3 attributes
eventsList.add(new Event(title, time, tsunamiAlert));
}
if (inputStream != null) {
inputStream.close();
}
} else {
Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return eventsList;
}
}
Add a method in your adapter like this:
public void setData(List<Event> data) {
this.data=data;
notifyDataSetChanged();
}
Which kind of error do you encounter?
I suggest using Java Interface and CallBack method for your AsynkTask, in this scenario, whenever your AsynkTask task is done, it notify the Activity with that callback method and you can execute notifyDataSetChange method of the adapter.

Android - Display data from Adapter in Listview

I've currently got an application that pulls data from a mysql database and displays it in raw JSON format. I'm currently working on pushing this data into a String variable and displaying it on a Listview on a specific activity.
Problem is, when trying to display this data, my Listview is not populating; I'm sure the variable is not empty as the if statement would have captured this.
Here is snippet of MainActivity code:
//Methods to grab information from abhandym_DB database
public void getJSON(View view){
new BackgroundTask().execute();
}
public void parseJSON(View view){
if(JSON_String==null){
Toast.makeText(getApplicationContext(), "First Get Json", Toast.LENGTH_LONG).show();
}else{
Intent intent = new Intent(this,Test.class);
intent.putExtra("JSON_Data",JSON_String);
startActivity(intent);
}
}
class BackgroundTask extends AsyncTask<Void,Void,String>{
String json_url;
#Override
protected void onPreExecute() {
json_url = "http://abhandyman.x10host.com/json_get_data.php";
}
#Override
protected String doInBackground(Void... params) {
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
InputStream inputSteam = httpURLConnection.getInputStream();
BufferedReader buffereredReader = new BufferedReader(new InputStreamReader(inputSteam));
StringBuilder stringBuilder = new StringBuilder();
while((JSON_String = buffereredReader.readLine())!=null){
stringBuilder.append(JSON_String+"\n");
}
buffereredReader.close();
inputSteam.close();
httpURLConnection.disconnect();
return stringBuilder.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
TextView textView = (TextView)findViewById(R.id.fragment1_textview_JSONAPPEAR);
textView.setText(result);
JSON_String = result;
}
}
Here is the code for my Test.java
public class Test extends AppCompatActivity {
String JSON_String;
JSONObject jsonObject;
JSONArray jsonArray;
DataAdapter dataAdapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
listView = (ListView)findViewById(R.id.test_listView);
dataAdapter = new DataAdapter(this, R.layout.row_layout);
listView.setAdapter(dataAdapter);
JSON_String = getIntent().getExtras().getString("JSON_Data");
try {
jsonObject = new JSONObject(JSON_String);
jsonArray = jsonObject.getJSONArray("server_response");
int count = 0;
String jobid,problem,resolution;
while(count<jsonObject.length()){
JSONObject JO = jsonArray.getJSONObject(count);
jobid = JO.getString("jobid");
problem = JO.getString("problem");
resolution = JO.getString("resolution");
Data data = new Data(jobid,problem,resolution);
dataAdapter.add(data);
count++;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Here is the code for my DataAdapter:
public class DataAdapter extends ArrayAdapter{
List list = new ArrayList();
public DataAdapter(Context context, int resource) {
super(context, resource);
}
public void add(Data object) {
super.add(object);
list.add(object);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
DataHolder dataHolder;
if(row == null){
LayoutInflater layoutInflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.row_layout,parent,false);
dataHolder = new DataHolder();
dataHolder.tx_jobid = (TextView) row.findViewById(R.id.tx_jobid);
dataHolder.tx_problem = (TextView) row.findViewById(R.id.tx_problem);
dataHolder.tx_resolution = (TextView) row.findViewById(R.id.tx_resolution);
row.setTag(dataHolder);
}else{
dataHolder = (DataHolder)row.getTag();
}
Data data = (Data)this.getItem(position);
dataHolder.tx_jobid.setText(data.getJobid());
dataHolder.tx_problem.setText(data.getProblem());
dataHolder.tx_resolution.setText(data.getResolution());
return row;
}
static class DataHolder{
TextView tx_jobid,tx_problem,tx_resolution;
}
}
and here is what it displays when clicking on "Parse JSON" button.
listView empty after population
Any help or advise on why its not displaying would be much appreciated!
Thanks in advance!
your problem seems to be here :
while(count<jsonObject.length()){
you're not looping using the number of array elements but using the number of mapped key:value object which is one (the "server_response") , you have to change this line to :
while(count<jsonArray.length()){
,
you have just the first element showing because jsonObject.length() will return 1 since it have just one element.
from the doc, JSONObject, length() method:
Returns the number of name/value mappings in this object.
and in your case you have just one name/value mapped ("server_response":[array items...])
Check in Test.java. I think You are setting the adapter to the listview before adding data to it
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
listView = (ListView)findViewById(R.id.test_listView);
dataAdapter = new DataAdapter(this, R.layout.row_layout);
JSON_String = getIntent().getExtras().getString("JSON_Data");
try {
jsonObject = new JSONObject(JSON_String);
jsonArray = jsonObject.getJSONArray("server_response");
int count = 0;
String jobid,problem,resolution;
while(count<jsonObject.length()){
JSONObject JO = jsonArray.getJSONObject(count);
jobid = JO.getString("jobid");
problem = JO.getString("problem");
resolution = JO.getString("resolution");
Data data = new Data(jobid,problem,resolution);
dataAdapter.add(data);
count++;
}
} catch (JSONException e) {
e.printStackTrace();
}
listView.setAdapter(dataAdapter); //change effected
}

onResume Does Not Update ListView With New Data

I am trying to update a ListView on previous fragment after back button press. The onResume is called (verified with Toast) and the webservice runs (listView is displayed after it is cleared). The problem is that the ListView is still showing old values and not new value after accessWebService_getUsername is called. I verify the values from MySQL and even though the DB is updated, the ListView only returns old values.
#Override
public void onResume() {
Toast.makeText(getActivity(), "onResume", Toast.LENGTH_SHORT).show();
super.onResume();
adapter.clear();
getIMEI();
accessWebService_getUsername();
adapter.notifyDataSetChanged();
}
Update:
//ListView
ListView lv =(ListView)view.findViewById(R.id.listView);
adapter = new ContactsAdapter(getActivity(), arrRequest_Contact, arrRequest_NameSurname, arrRequest_MessageCount, arrRequest_Time, arrRequest_Image);
lv.setAdapter(adapter);
// Json
private class JsonGetUsername extends AsyncTask<String, Void, String> {
//Pending 01
private ProgressDialog dialog = new ProgressDialog(getActivity());
#Override
protected void onPreExecute() {
this.dialog.setMessage("Loading Contacts, Please Wait");
this.dialog.show();
}
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
}
catch (IOException e) {
// e.printStackTrace();
Toast.makeText(getActivity(),"Error..." + e.toString(), Toast.LENGTH_LONG).show();
}
return answer;
}
#Override
protected void onPostExecute(String result) {
//Pending 02
if (dialog.isShowing()) {
dialog.dismiss();
}
adapter.notifyDataSetChanged();
try{
ListDrawer_getUsername(); //has ConnectionException (when it cannot reach server)
}catch (Exception e){
Toast.makeText(getActivity(), "Please check your connection..", Toast.LENGTH_LONG).show();
}
}
}// end async task
public void accessWebService_getUsername() {
JsonGetUsername task = new JsonGetUsername();
// passes values for the urls string array
task.execute(new String[] { "http://mywebsite/php/get_username.php?pIMEI="+IMEI});
}
// build hash set for list view
public void ListDrawer_getUsername() {
try {
JSONObject jsonResponse = new JSONObject(jsonResult);
JSONArray jsonMainNode = jsonResponse.optJSONArray("username_info");
for (int i = 0; i < jsonMainNode.length(); i++) {
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
request_username = jsonChildNode.optString("Username");
}
accessWebService_getContacts();
} catch (JSONException e) {
System.out.println("Json Error Rooms" +e.toString());
//Toast.makeText(getApplicationContext(), "No Rooms To Load", Toast.LENGTH_SHORT).show();
}
}
UPDATE 2:
//ContactsAdpater
class ContactsAdapter extends ArrayAdapter<String>
{
Context context;
List<String> Request_Contact;
List<String> Request_NameSurname;
List<String> Request_MessageCount;
List<String> Request_Time;
List<String> Request_Image;
ContactsAdapter(Context c, List<String> Request_Contact, List<String> Request_NameSurname, List<String> Request_MessageCount, List<String> Request_Time, List<String> Request_Image)
{
super(c, R.layout.activity_contacts_single, R.id.textContact, Request_Contact);
this.context=c;
this.Request_Contact=Request_Contact;
this.Request_NameSurname=Request_NameSurname;
this.Request_MessageCount=Request_MessageCount;
this.Request_Time=Request_Time;
this.Request_Image=Request_Image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row=convertView;
if(row==null)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.activity_contacts_single, parent, false);
}
TextView txtContact = (TextView) row.findViewById(R.id.textContact);
TextView txtNameSurname = (TextView) row.findViewById(R.id.textNameSurname);
TextView txtMessageCount = (TextView) row.findViewById(R.id.textMessageCount);
TextView txtTime = (TextView) row.findViewById(R.id.textTime);
ImageView imageView = (ImageView) row.findViewById(R.id.imageView);
txtContact.setText(Request_Contact.get(position));
txtNameSurname.setText(Request_NameSurname.get(position));
txtMessageCount.setText(Request_MessageCount.get(position));
txtTime.setText(Request_Time.get(position));
Picasso.with(context).load(arrRequest_Image.get(position)).transform(new CircleTransform()).placeholder(R.drawable.ic_launcher).into(imageView);
return row;
}
}
You'll need to override the clear method in your ContactsAdapter to actually clear the lists you are storing your data in.
It looks like you'll need to clear all your lists, so if you add this to ContactsAdapter, your code should work as expected:
#Override
public void clear() {
super.clear();
Request_Contact.clear();
Request_NameSurname.clear();
Request_MessageCount.clear();
Request_Time.clear();
Request_Image.clear();
}

Stop creating fragmnet view until i have parsed all data from Json.

I receive a null pointer exeception when trying to populate the interface beacuse I have no data in my instance object.
I am using a login button and call a service, i receive a json and after I parse it i have a status handler...login ok... Here I want to start an asynk task to get some photo data
public void StatusHandlerLogin(String status, Activity currentActivity) {
if (status.equals("0")) {
new GetPhotoDataTask(currentActivity).execute();
Intent intent = new Intent(currentActivity,
NavigationActivity.class);
currentActivity.startActivity(intent);
}
//}
The asynk task is like this
public class GetPhotoDataTask extends
AsyncTask<Void, Void, List<PhotoData>> {
Activity activity;
public GetPhotoDataTask(Activity activity) {
this.activity = activity;
}
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
Log.d("GetPhotoDataTask onPreExecute",
"GetPhotoDataTask onPreExecute");
super.onPreExecute();
progressDialog = ProgressDialog.show(activity, "Preluare Date",
"Va rugam asteptati!");
}
#Override
protected List<PhotoData> doInBackground(Void... params) {
Log.d("GetPhotoDataTask doInBackground",
"GetPhotoDataTask doInBackground");
MyStyleApi myStyleApi = new MyStyleApi();
List<PhotoData> photoData = null;
try {
photoData = myStyleApi.getPhotoDataWithDispatch();
} catch (JSONException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
List<String> photoStr = new ArrayList<String>();
for (int i = 0; i < photoData.size(); i++) {
photoStr.add(photoData.get(i).getPhotoURL());
}
String[] photoUrls = new String[photoStr.size()];
photoUrls = photoStr.toArray(photoUrls);
for (int i = 0; i < photoUrls.length; i++) {
if (photoUrls[i].contains("\"")) {
photoUrls[i] = photoUrls[i].replace("\"", "");
}
}
AppManager.getInstance().setphotoUrls(photoUrls);
List<PhotoData> photoDataS = AppManager.getInstance().setPhotoData(
photoData);
return photoData;
}
protected void onProgressUpdate(Integer... percent) {
progressDialog = ProgressDialog.show(activity, "Preluare Date",
"Va rugam asteptati!");
}
protected void onPostExecute(List<PhotoData> photoData) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
on do in background i have a method that call other service
get PhotoData with userId as param
public List<PhotoData> getPhotoDataWithDispatch() throws JSONException,
ClientProtocolException, IOException {
Log.d("getPhotoDataWithDispatch ", "getPhotoDataWithDispatch ");
UserData data = AppManager.getInstance().getUserData();
String userID = data.getUserID();
if (userID.contains("\"")) {
userID = userID.replace("\"", "");
}
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("userID", userID);
JsonArray response = WebServiceApi.PostToServiceWithStringResponse(
"images/get_images_data", params);
List<PhotoData> photoDataList = new ArrayList<PhotoData>();
if (response != null) {
photoDataList = parseJsonArrayForFotoData(response);
}
return photoDataList;
}
and if response is not null i parse it
public static List<PhotoData> parseJsonArrayForFotoData(JsonArray jsonArray) {
List<PhotoData> photoDataList = new ArrayList<PhotoData>();
for (int i = 0; i < jsonArray.size(); i++) {
Log.d("getPhotoDataWithDispatch ", "getPhotoDataWithDispatch ");
JsonElement photoID = ((JsonObject) jsonArray.get(i)).get("pozaID");
JsonElement photoUrl = ((JsonObject) jsonArray.get(i))
.get("pozaURL");
JsonElement thumbURL = ((JsonObject) jsonArray.get(i))
.get("thumbURL");
JsonElement tags = ((JsonObject) jsonArray.get(i)).get("tags");
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(tags.toString()).getAsJsonArray();
List<Tags> tagsList = new ArrayList<Tags>();
for (int j = 0; j < array.size(); j++) {
JsonElement tagId = ((JsonObject) array.get(j)).get("tagID");
JsonElement coordX = ((JsonObject) array.get(j)).get("coordX");
JsonElement coordY = ((JsonObject) array.get(j)).get("coordY");
JsonElement productId = ((JsonObject) array.get(j))
.get("productID");
Tags tagPData = new Tags(tagId.toString(), coordX.toString(),
coordY.toString(), productId.toString());
tagsList.add(tagPData);
}
PhotoData photoData = new PhotoData(photoID.toString(),
photoUrl.toString(), thumbURL.toString(), null, tagsList);
photoDataList.add(photoData);
}
return photoDataList;
}
ok in GetPhotoDataTaskFb do in background i set the instance of the photos object
AppManager.getInstance().setphotoUrls(photoUrls);
and in fragmnet
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.ac_image_pager, container,
false);
// Dummy code
if (counter == 0) {
for (int i = 0; i <= 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
counter++;
String[] imageUrls = AppManager.getInstance().getphotoUrls();
//here is where i get the null.. i tried some dummy code to delay and receive data but it is not working
How can I manage to stop create view until all data is parsed?

Can I use AsyncTask inside ListFragment? or should I use AsyncTaskLoader?

I tried the code below and also tried the AsyncTaskLoader approach. The app crashes when I instantiate the AsyncTask. Pleas advise me on the best approach to load JSON in a list fragment inside tab host.
The code below is the tab fragment (I use action bar tabs in main activity):
public class TabTop extends ListFragment {
Context context = getActivity().getBaseContext();
String API_URL = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
ArrayList<Deal> deals;
DealsListAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
#SuppressWarnings("unused")
int a = 0;
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
GetTopDeals getTopDeals = new GetTopDeals(context);
getTopDeals.execute(API_URL);
super.onActivityCreated(savedInstanceState);
}
class GetTopDeals extends AsyncTask<String, Void, ArrayList<Deal>>{
ProgressDialog progressDialog;
public GetTopDeals(Context activity) {
this.progressDialog = new ProgressDialog(activity);
}
#Override
protected void onPostExecute(ArrayList<Deal> result) {
adapter = new DealsListAdapter(context, result);
setListAdapter(adapter);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
progressDialog.setCancelable(true);
progressDialog.setProgress(0);
progressDialog.setMessage("loading Top deals...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
super.onPreExecute();
}
#Override
protected ArrayList<Deal> doInBackground(String... urls) {
String response = sendRequest(urls[0]); // make request for json
return processResponse(response); // parse the Json and return ArrayList to postExecute
}
private String sendRequest(String apiUrl) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL url = new URL(apiUrl);
httpCon = (HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
}
public ArrayList<Deal> processResponse(String response) {
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new ArrayList<Deal>();
for (int i = 0; i < results.length(); i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
int api_id = jMovie.getInt("id");
String name = jMovie.getString("title");
String content = jMovie.getString("synopsis");
JSONObject posters = jMovie.getJSONObject("posters");
String image_url = posters.getString("profile");
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(getActivity().getBaseContext(), DealInformation.class);
startActivity(intent);
super.onListItemClick(l, v, position, id);
}
}
Make your asynctask in his own file.
And when your asynctask is finish, implement OnPostExecute which is automatically call. Notify your adapter by a notifyDataSetChanged like that :
#Override
protected void onPostExecute(List<NewItem> list) {
Adapter.getListe().clear();
Adapter.getListe().addAll(list);
Adapter.notifyDataSetChanged();
}
thank you guys,
i want to post my answer. after some research i decided to go with AsyncTaskLoader.
this is my code
public class TabOurPicks extends ListFragment implements LoaderCallbacks<String[]> {
// when activity loads- onActivityCreated() calls the initLoader() who activate onCreateLoader()
#Override
public void onActivityCreated(Bundle savedInstance) {
super.onActivityCreated(savedInstance);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{}));
getLoaderManager().initLoader(0, null,this).forceLoad();
}
// onCreateLoader instantiate the asynctaskloaser who work in bg
#Override
public RSSLoader onCreateLoader(int arg0, Bundle arg1) {
return new RSSLoader(getActivity()); //
}
// after bg process invoke onLoadFinished() who work in ui thread
#Override
public void onLoadFinished(Loader<String[]> loader, String[] data) {
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, data
) );
}
#Override
public void onLoaderReset(Loader<String[]> arg0) {
// TODO Auto-generated method stub
}
and this is the inner class for the loader:
static public class RSSLoader extends AsyncTaskLoader<String[]>
{
public RSSLoader(Context context) {
super(context);
}
#Override
public String[] loadInBackground() {
String url = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
String response = sendRequest(url);
return processResponse(response);
}
private String sendRequest(String url) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL apiUrl = new URL(url);
httpCon = (HttpURLConnection) apiUrl.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
private String[] processResponse(String response) {
String[] deals = null;
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new String[10];
for (int i = 0; i < 9; i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
String name = jMovie.getString("title");
deals[i] = name;
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
}
}
It doesn't matter if your asynctask has its own file. You just don't want your activity to extends asynctask as this would make your activity asynchronous - but this is impossible to do anyways due to java's double inheritance rule.
Based on the architecture of your app and your programming style the asyntask can be an inner class in the activity. on the PostExecute method make sure you have given data to your adapter and that the adapter is set to the list, then just run notifyDataSetChanged().
Assuming your asynctask is loading data from cache or the network you are on the right track with your approach to this.

Categories

Resources