Passing Serializable Objects using AsyncTask - java

So I am parsing a JSONObject using the JSON Parser, and put that data into several objects using an AsyncTask. My question is: How would I pass all these objects? They are all Serializable and I've read that you can just create an Intent and put the objects into the Intent using the putExtras method; however, when I do this, I get an error.
Also, to create all the objects, I call the constructors of each of the different objects using constructors, in the original constructor. So I can call one constructor, and that constructor call the other constructors, using methods within the first constructor. I know it might sound a little confusing, but ultimately the parser creates 8 different objects that I want to pass to the next activity.
I'm open to any suggestions on how to do this.
EDIT: I don't want to useParcelable it is far to complex for what I am trying to do and I am not worrying about speed as my file is small.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
checkWifiConnection(menuUrl);
}
class LoadJSON extends AsyncTask<String, Void, Restaurant>{
#Override
protected Restaurant doInBackground(String... params) {
JSONObject jo=null;
Restaurant rest = null;
try {
Log.i(TAG, "Running background thread");
URL mURL = new URL(menuUrl);
Log.i(TAG, mURL + ": menuUrl");
URLConnection uc = mURL.openConnection();
JsonParser parser = new JsonParser();
try {
jo = parser.getJson(getApplicationContext(), uc);
rest = new Restaurant(jo); <<-- Start the parsing using this constructor, which calls the other objects constructors
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return rest;
}
#Override
protected void onPostExecute(Restaurant rest){
ImageButton ib = (ImageButton)findViewById(R.id.continuebutton);
ib.setVisibility(View.VISIBLE);
ib.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent homeIntent = new Intent(MainActivity.this, HomeActivity.class);
homeIntent.putExtra("Restaurant", rest); //<< get an error here
startActivity(homeIntent);
}
});
}
Here is the Restaurant class:
package com.uie.menu.app;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class Restaurant implements Serializable {
private final static String TAG = Restaurant.class.getSimpleName();
String name;
String category;
String created_at;
String updated_at;
private List<Menu> menuList;
private List<SideDishes> sideDishes;
private List<Drinks> drinks;
private List<Ingredients> ingredients;
private List<DrinkCategories> drinkCategories;
private Restaurant() {
menuList = new ArrayList<Menu>();
sideDishes = new ArrayList<SideDishes>();
drinks = new ArrayList<Drinks>();
ingredients = new ArrayList<Ingredients>();
drinkCategories = new ArrayList<DrinkCategories>();
}
public Restaurant(JSONObject jo) throws JSONException {
this();
if (jo != null) {
this.name = jo.optString("name");
Log.i(TAG, name + " : Restaurant 'name'");
this.category = jo.optString("category");
Log.i(TAG, category + " : Restaurant category");
this.created_at = jo.optString("created_at");
Log.i(TAG, created_at + " : Restaurant 'created at'");
this.updated_at = jo.optString("updated_at");
Log.i(TAG, updated_at + " : Restaurant 'updated_at'");
addMenus(jo);
addMenuSides(jo);
addMenuDrinks(jo);
addMenuIngredients(jo);
addDrinkCategories(jo);
}
}
private void addMenus(JSONObject jo) throws JSONException {
JSONArray menus = jo.optJSONArray("menus");
if (menus != null) {
for (int ii = 0; menus != null && ii < menus.length(); ii++) {
JSONObject menu = menus.optJSONObject(ii);
Log.d(TAG, "==Adding Restaurant Menu==");
addMenu(new Menu(menu));
}
Log.d(TAG, "==Done adding Restaurant Menu==");
}
}
private void addMenu(Menu menu) {
menuList.add(menu);
}
private void addMenuSides(JSONObject jo) throws JSONException{
JSONArray sides = jo.optJSONArray("side_dishes");
if (sides != null) {
for (int ii = 0; sides != null && ii < sides.length(); ii++) {
JSONObject side = sides.optJSONObject(ii);
Log.d(TAG, "==Adding Restaurant Side Dish==");
addSide(new SideDishes(side));
}
Log.d(TAG, "==Done adding Restaurant Side Dishes==");
}
}
private void addSide(SideDishes side){
sideDishes.add(side);
}
private void addMenuDrinks(JSONObject jo) throws JSONException{
JSONArray drinks = jo.optJSONArray("drinks");
if (drinks != null) {
for (int ii = 0; drinks != null && ii < drinks.length(); ii++) {
JSONObject drink = drinks.optJSONObject(ii);
Log.d(TAG, "==Adding Restaurant Drinks==");
addDrink(new Drinks(drink));
}
Log.d(TAG, "==Done adding Restaurant Drinks==");
}
}
private void addDrink(Drinks drink){
drinks.add(drink);
}
private void addMenuIngredients(JSONObject jo){
JSONArray ingredients = jo.optJSONArray("ingredients");
if (ingredients != null) {
Log.d(TAG, "==Adding Restaurant Ingredient==");
for (int ii = 0; ingredients != null && ii < ingredients.length(); ii++) {
JSONObject ingredient = ingredients.optJSONObject(ii);
addIngredient(new Ingredients(ingredient));
}
Log.d(TAG, "==Done adding Restaurant Ingredients==");
}
}
private void addIngredient(Ingredients ingredient){
ingredients.add(ingredient);
}
private void addDrinkCategories(JSONObject jo) throws JSONException{
JSONArray drinkCategories = jo.optJSONArray("drink_categories");
if (drinkCategories != null) {
Log.d(TAG, "==Adding Restaurant Drink Categories==");
for (int ii = 0; drinkCategories != null && ii < drinkCategories.length(); ii++) {
JSONObject drinkCategory = drinkCategories.optJSONObject(ii);
addCategory(new DrinkCategories(drinkCategory));
}
Log.d(TAG, "==Done adding Restaurant Drink Categories==");
}
}
private void addCategory(DrinkCategories drinkCategory){
drinkCategories.add(drinkCategory);
}
}
There error that I get is: Cannot refer to a non-final variable rest inside an inner class defined in a different method

Try declaring your rest object in the class scope of LoadJSON, instead of inside doInBackground method. e.g.
class LoadJSON extends AsyncTask<String, Void, Restaurant>{
Restaurant rest = null;
private void doInBackground(...) {
...
}
}

Restaurant should implements Parcelable, it's the best way to pass objects to another activity from Intent.
Edit: You may encounter another bug later, related to you Lists inside the Serializable Restaurant. it's explained here

Related

How to make ViewModel display network data on first run

I am just getting into Android Architecture and have encountered an issue after following this tutorial by mitch:
ViewModel doesn't show any data from the internet- I'm using volley- on first run.
The UI remains blank and only shows data on the views only onChange. i.e A screen rotation/refresh
If I manually set this data, it shows them on first run as required
i.e dataSet.add(new DecodeHouseDetails(1,1,1,"H2345","treutue.jpg","House 1","4345423232312","3224342434232") ); //Add data to the mutatable list
But once I include the network data, it misbehaves.
I have tried checking if my repository could be returning a null list on first run but the toast attached inside the repository shows that the data was well received, only that I dont understand why it wont display until either a change in screen rotation or a refresh
My Repository
public class GetHouseDetailsRepository {
private Context mContext;
private static final String URL_initializeDashboard= CustomFunctions.root_house_admin_url+"initialize_dashboard";
CustomFunctions func= new CustomFunctions();
private static GetHouseDetailsRepository instance;
private ArrayList<DecodeHouseDetails> dataSet= new ArrayList<>();
private JSONObject jsonObject;
public static GetHouseDetailsRepository getInstance(){
if(instance == null){
instance = new GetHouseDetailsRepository();
}
return instance;
}
//Make a mutable list of the data that we will be getting from the database
public MutableLiveData<List<DecodeHouseDetails>> getHouseDetails(Context mContext){
this.mContext=mContext;
getDatabaseHouseDetails();
MutableLiveData<List<DecodeHouseDetails>> myData= new MutableLiveData<>();
if(dataSet ==null){
getDatabaseHouseDetails();
}
myData.setValue(dataSet);
return myData;
}
//Method to actually get the data from the database
public void getDatabaseHouseDetails(){
//dataSet.add(new DecodeHouseDetails(1,1,1,"H2345","treutue.jpg","Keja Mkononi","1","A nice house","Water,electrivit","Other amenities","5","1","Embu","1","1","1","1","4345423232312","3224342434232") ); //Add data to the mutatable list
jsonObject= new JSONObject();
try {
jsonObject.put("me",""+func.getSharedUserID(mContext) );//Logged in user
} catch (JSONException e) {
Log.e("JSONObject Here", e.toString());
}
VolleyNetworkRequestInterfaceSingleton.getResponse(mContext,Request.Method.GET, URL_initializeDashboard, jsonObject,new VolleyNetworkRequestInterfaceSingleton.VolleyCallback(){
#Override
public void onSuccessResponse(String response) {
if(response!=null) {
try {
JSONObject json = new JSONObject(response);
//Successfully fetched
String sarray = json.getString("house_details");
Toast.makeText(mContext, sarray, Toast.LENGTH_SHORT).show();
JSONArray jsonArray = new JSONArray(sarray);
//Clear list to refresh list in every selection
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json_list = jsonArray.getJSONObject(i);
DecodeHouseDetails houses_array = new DecodeHouseDetails(
json_list.getInt("active_identifier"),
json_list.getInt("house_id"),
json_list.getInt("house_status"),
json_list.getString("house_number"),
json_list.getString("house_cover"),
json_list.getString("house_name"),
json_list.getString("longitude"),
json_list.getString("latitude")
);
dataSet.add(houses_array);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
}
}
My ViewModel
public class GetHouseDetailsViewModel extends AndroidViewModel {
//The data we fetch from asynchronously
private MutableLiveData<List<DecodeHouseDetails>> mHouseDetailsList;
private GetHouseDetailsRepository mHouseDetailsRepository;
public GetHouseDetailsViewModel(#NonNull Application application) {
super(application);
}
public void init(){
if(mHouseDetailsList != null){
mHouseDetailsList= new MutableLiveData<>();
}
mHouseDetailsRepository = GetHouseDetailsRepository.getInstance(); //Initialize the repository
mHouseDetailsList = mHouseDetailsRepository.getHouseDetails(this.getApplication());
}
public LiveData<List<DecodeHouseDetails>> getHouseInfo() {
if(mHouseDetailsList == null){
mHouseDetailsList = new MutableLiveData<>();
}
return mHouseDetailsList;
}
}
My View - Fragment
public class AdmManageHouses extends Fragment {
private ProgressBar progressloader,progressloader_large;
SwipeRefreshLayout refreshLayout;
private TextView house_number_text,house_title_text,house_name_text;
private GetHouseDetailsViewModel mHouseDetailsViewModel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab1_manage_houses, container, false);
mHouseDetailsViewModel = ViewModelProviders.of(getActivity()).get(GetHouseDetailsViewModel.class);
//Innitialize objects
house_title_text= rootView.findViewById(R.id.house_title);
house_number_text= rootView.findViewById(R.id.house_number);
house_name_text= rootView.findViewById(R.id.house_name);
//Initialize the view model
mHouseDetailsViewModel.init();
mHouseDetailsViewModel.getHouseInfo().observe(getViewLifecycleOwner(), new Observer<List<DecodeHouseDetails>>() {
#Override
public void onChanged(List<DecodeHouseDetails> decodeHouseDetails) {
for(int i=0; i<decodeHouseDetails.size(); i++) {
house_number_text.setText(String.valueOf(decodeHouseDetails.get(i).getHouse_number()));
house_title_text.setText(decodeHouseDetails.get(i).getHouse_name());
house_name_text.setText(decodeHouseDetails.get(i).getHouse_name());
}
}
});
//Refresh on swipe
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
initializeDashboard();
refreshLayout.setRefreshing(false);
}
});
initializeDashboard();
return rootView;
}
private void initializeDashboard() {
for(int i=0; i<mHouseDetailsViewModel.getHouseInfo().getValue().size(); i++) {
house_number_text.setText(String.valueOf(mHouseDetailsViewModel.getHouseInfo().getValue().get(i).getHouse_number()));
house_title_text.setText(mHouseDetailsViewModel.getHouseInfo().getValue().get(i).getHouse_name());
house_name_text.setText(mHouseDetailsViewModel.getHouseInfo().getValue().get(i).getHouse_name());
}
}
}
After thorough checking of the viewmodel, I discovered that problem was in the repository and not the viewModel. I was not calling setValue() properly.
This made the first run - when the list is null - fail to populate the UI until onChange.
I made the following changes to the repository
i.e
Declare myData variable
Private MutableLiveData<List<DecodeHouseDetails>> myData= new MutableLiveData<>();
//Make a mutable list of the data that we will be getting from the database
public MutableLiveData<List<DecodeHouseDetails>> getHouseDetails(Context mContext){
this.mContext=mContext;
getDatabaseHouseDetails();
return myData;
}
//Method to actually get the data from the database
public void getDatabaseHouseDetails(){
//dataSet.add(new DecodeHouseDetails(1,1,1,"H2345","treutue.jpg","Keja Mkononi","1","A nice house","Water,electrivit","Other amenities","5","1","Embu","1","1","1","1","4345423232312","3224342434232") ); //Add data to the mutatable list
jsonObject= new JSONObject();
try {
jsonObject.put("me",""+func.getSharedUserID(mContext) );//Logged in user
} catch (JSONException e) {
Log.e("JSONObject Here", e.toString());
}
VolleyNetworkRequestInterfaceSingleton.getResponse(mContext,Request.Method.GET, URL_initializeDashboard, jsonObject,new VolleyNetworkRequestInterfaceSingleton.VolleyCallback(){
#Override
public void onSuccessResponse(String response) {
if(response!=null) {
try {
JSONObject json = new JSONObject(response);
//Successfully fetched
String sarray = json.getString("house_details");
Toast.makeText(mContext, sarray, Toast.LENGTH_SHORT).show();
JSONArray jsonArray = new JSONArray(sarray);
//Clear list to refresh list in every selection
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json_list = jsonArray.getJSONObject(i);
DecodeHouseDetails houses_array = new DecodeHouseDetails(
json_list.getInt("active_identifier"),
json_list.getInt("house_id"),
json_list.getInt("house_status"),
json_list.getString("house_number"),
json_list.getString("house_cover"),
json_list.getString("house_name"),
json_list.getString("longitude"),
json_list.getString("latitude")
);
dataSet.add(houses_array);
}
myData.setValue(dataSet);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
}

How to send values from an arraylist from AsyncTask class to another class in Android?

I have the next problem, I tried to send Arraylist<string> values from AsyncTask class to other class call graphics but I don’t know what I do wrong and how to get Arraylist<string> values in the other class, because I have a lot of sintaxis errors I my code
AsyncTask class
public class fetch extends AsyncTask<Void,Void,ArrayList<String>> {
//v funcional
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected ArrayList<String> doInBackground(Void... voids) {
String Id ="";
String Time ="";
String Pressure="";
ArrayList<String> IdArray = new ArrayList<String>();
ArrayList<String> TimeArray = new ArrayList<String>();
ArrayList<String> PressureArray = new ArrayList<String>();
String IdS=""+IdArray;
String TimeS=""+TimeArray;
String PresureS=""+PressureArray;
data.set(1,TimeS);
data.set(2,TimeS);
data.set(3,TimeS);
return data;
}
#Override
protected void onPostExecute(ArrayList<String> result){
super.onPostExecute(result);
Graphics.data.setText(data);
}}
The graphics class
public class Graphics extends AppCompatActivity {
public static TextView data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.graphics);
Button firstButton = (Button) findViewById(R.id.json);
data = (TextView) findViewById(R.id.msgTxt);
firstButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fetch process = new fetch();
ArrayList<String> data= process.execute();
data.get(1);
}
});
}
you can create an interface which your "Graphics" implements it , and pass it to your AsyncTask class.
like this
public interface BlaBlaBla {
void doBla(ArrayList<String> myBla);
}
and in your "Graphics" :
class Graphics extends AppCompatActivity implements BlaBlaBla {
fetch process = new fetch(this);
}
and for asyncClass :
public class fetch extends AsyncTask<Void,Void,ArrayList<String>> {
//constructor
BlaBlaBla bla;
public fetch(BlaBlaBla bla){
this.bla=bla;
}
//when your task is complete use bla.doBla(pass your array here);
}
my solution
Fetch class
public class Fetch extends AsyncTask<Void,Void,String[][]> {
public static int KEY = 0;
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected String[][] doInBackground(Void... voids) {
HttpHandler sh = new HttpHandler();
String url = "http:xxxxxxx/xxx.json";
String jsonStr = sh.makeServiceCall(url);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(jsonStr);
int nTiempos=jsonObj.length();
String[] IdKeyArray = new String[nTie];
for (int i = 0; i < jsonObj.length(); i++) {
JSONObject c = jsonObj.getJSONObject(String.valueOf(i));
IdKeyArray[i] = c.getString("Key");
String[][] valores={IdKeyArray};
return valores;
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
And this is the "call" the other class where I get the values
private String[][] valores;
Fetch process = new Fetch();
process.execute();
try {
valores=process.get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
pm.setText(String.valueOf(valores[Fetch.Key][0]));
}
}
}

how to make a condition to data from json

i want to make a condition when i call the json and make it to 'you cannot have the same thing' in the json value when you want to add more data to database.
this is my code
String nim2, ruang2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_kelas);
nim = (EditText) findViewById(R.id.editNim);
ruang = (EditText) findViewById(R.id.ruangPinjam);
new daftarMahasiswa().execute();
}
public void nextButton (View view) {
nim2 = nim.getText().toString();
ruang2 = ruang.getText().toString();
if (ruang2.equals(ruangan)) {
Toast.makeText(KelasActivity.this, "this room has already borrow",Toast.LENGTH_LONG).show();
ruang.setError("you cannot borrow the room again");
}else if (nim2.equals(nimMahasiswa)){
Toast.makeText(KelasActivity.this, "this NIM has borrow the room",Toast.LENGTH_LONG).show();
nim.setError("you cannot borrow it again");
}
class daftarMahasiswa extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(KelasActivity.this);
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... params) {
String link_url = "http://192.168.43.54/datapeminjamankelas/read_mahasiswa.php";
JSONParser jParser = new JSONParser();
JSONObject json = null;
try {
json = jParser.AmbilJson(link_url);
} catch (JSONException e) {
e.printStackTrace();
}
try {
str_json = json.getJSONArray("data");
for (int i = 0; i < str_json.length(); i++) {
JSONObject ar = str_json.getJSONObject(i);
ruangan = ar.getString("ruang").trim();
nimMahasiswa = ar.getString("nim").trim();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
pDialog.dismiss();
}
}
and this is my json
{
"data": [
{
"nim": "103452",
"ruang": "2702"
},
{
"nim": "102341",
"ruang": "2504"
},
{
"nim": "103421",
"ruang": "1101"
}
]
}
what i want to make is the 'nim' and the 'ruang' from json cannot be add again with the same value. it works honestly but only when the data just have 1, when it have more it dont work anymore. please help what can i put to make it right
You can add 'nim' and 'ruang' values in separate List and from there, you can check whether the entered value is already present or not.
List<String> nimList = new ArrayList<>();
List<String> ruangList = new ArrayList<>();
for (int i = 0; i < str_json.length(); i++) {
JSONObject ar = str_json.getJSONObject(i);
ruangan = ar.getString("ruang").trim();
nimMahasiswa = ar.getString("nim").trim();
nimList.add(nimMahasiswa);
ruangList.add(ruangan);
}
You can check like below:
nim2 = nim.getText().toString();
ruang2 = ruang.getText().toString();
if (ruangList.contains(ruang2)) {
Toast.makeText(KelasActivity.this, "this room has already borrow",Toast.LENGTH_LONG).show();
ruang.setError("you cannot borrow the room again");
}else if (nimList.contains(nim2)){
Toast.makeText(KelasActivity.this, "this NIM has borrow the room",Toast.LENGTH_LONG).show();
nim.setError("you cannot borrow it again");
}
Better you could have a pojo class and override equals method like below
public class MyData {
private String myNim;
private String myRuang;
//setter & getters here
#Override
public boolean equals(Object obj) {
if(obj instanceOf MyData)
{
MyData myData = (MyData) obj;
return myData.getMyNim().equals(this.myNim)&&myData.getMyRuang().equals(this.myRuang);
}
return false;
}
}
and now you can check the element exist or not by using below code.
try {
str_json = json.getJSONArray("data");
List<MyData> myDataList = new ArrayList<MyData>();
for (int i = 0; i < str_json.length(); i++) {
JSONObject ar = str_json.getJSONObject(i);
ruangan = ar.getString("ruang").trim();
nimMahasiswa = ar.getString("nim").trim();
MyData myData = new MyData();
myData.setMyNim(nimMahasiswa);
myData.setMyRuang(ruangan);
if(myDataList.contains(myData))
//use your logic here to show error 'you cannot have the same thing'
else
myDataList.add(myData);
}
} catch (JSONException e) {
e.printStackTrace();
}
now you can use the myDataList which is having unique elements.

how do I get the value of a list outside the asynchronous method?

I've done a search on another stackoverflow post for 2 hours but still can not solve this problem. I have a variable called copyAudioListIqro with List String datatype in DetailMemilihIqro Activity class. When the variable called audioIqros in the AsyncTask class (precisely in the onPostExecute method) this list has a value from my json and I want to copy audioIqros variable to copyAudioListIqro via updateData method (outside the asynctask class). When I see the log monitor on updateData method I can see the value from copyAudioListIqro, but the problem is, when I access it via readDataAudioURL method(outside the asynctask class) copyAudioListIqro variable becomes null.
What is the solution for this problem?
Thank you
Here is the overall DetailMemilihIqro class
public class DetailMemilhIqro extends AppCompatActivity {
private ProgressDialog pDialog;
private List<ModelAudioIqro> audioIqros;
private List<String> copyAudioListIqro;
private AudioAdapter mAdapter;
private RecyclerView recyclerView;
private String TAG = DetailMemilihIqro.class.getSimpleName();
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_memilih_iqro);
recyclerView = (RecyclerView) findViewById(R.id.rvCVAudioIqro);
pDialog = new ProgressDialog(this);
audioIqros = new ArrayList<>();
mAdapter = new AudioAdapter(getApplicationContext(), audioIqros);
context = getApplicationContext();
copyAudioListIqro = new ArrayList<>();
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
Bundle getPosition = getIntent().getExtras();
int position = getPosition.getInt("positionUserClicked");
Log.d(TAG, "Position User clicked " + position);
if (position == 0) {
String endpoint = "http://latihcoding.com/jsonfile/audioiqro1.json";
new DownloadTask().execute(endpoint);
} else if (position == 1) {
String endpoint = "http://latihcoding.com/jsonfile/audioiqro2.json";
new DownloadTask().execute(endpoint);
} else if (position == 2) {
String endpoint = "http://latihcoding.com/jsonfile/audioiqro3.json";
new DownloadTask().execute(endpoint);
}
readDataAudioURL();
}
public void updateData(List<String> pathUrl) {
for (int i = 0; i < pathUrl.size(); i++) copyAudioListIqro.add(pathUrl.get(i));
Log.d(TAG, "updateData Method " + copyAudioListIqro.toString());
}
public void readDataAudioURL() {
Log.d(TAG, "readDataAudioURL Method " + copyAudioListIqro.toString());
}
public class DownloadTask extends AsyncTask<String, Void, List<String>> {
List<String> modelAudioIqroList;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog.setMessage("Downloading json...");
pDialog.show();
}
#Override
protected List<String> doInBackground(String... strings) {
modelAudioIqroList = new ArrayList<>();
int result;
HttpURLConnection urlConnection;
try {
URL url = new URL(strings[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
Log.d(TAG, "Result " + result);
} else {
//"Failed to fetch data!";
result = 0;
Log.d(TAG, "Result " + result);
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return modelAudioIqroList; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(List<String> audioIqros) {
super.onPostExecute(audioIqros);
pDialog.hide();
if (!audioIqros.isEmpty()) {
updateData(modelAudioIqroList);
} else {
Toast.makeText(context, "Empty", Toast.LENGTH_SHORT).show();
}
}
private void parseResult(String result) {
try {
JSONArray response = new JSONArray(result);
for (int i = 0; i < response.length(); i++) {
JSONObject object = response.getJSONObject(i);
ModelAudioIqro modelAudioIqro = new ModelAudioIqro();
modelAudioIqro.setName(object.getString("name"));
modelAudioIqro.setUrl(object.getString("url"));
String path = modelAudioIqro.getUrl();
Log.d(TAG, "String path " + path);
modelAudioIqroList.add(path);
}
} catch (JSONException e) {
e.printStackTrace();
}
mAdapter.notifyDataSetChanged();
}
}
}
Log for the copyAudioListIqro in the updateDataMethod
Log for the copyAudioListIqro in the readDataAudioURL
readDataAudioURL() call, that is a plain Log call, should be moved. Infact the task is asynch by nature, so oblivously the variable copyAudioListIqro won't have been initialized right after the task's start (.execute() method).
You're doing right, anyway, in notyfiying dataset change to list...You should just move it to postExecute as well...
I suggest to move all "after network" code to that postExecute, so that UI can be updated asynchronously ONLY when data is available and without blocking main thread. You can 'read' variables in the inner class, so just declare them final:
#Override
protected void onPostExecute(List<String> audioIqros) {
super.onPostExecute(audioIqros);
pDialog.hide();
if (!audioIqros.isEmpty()) {
updateData(modelAudioIqroList);
//data is now updated, notify datasets and/or send broadcast
mAdapter.notifyDataSetChanged();
readDataAudioURL();
} else {
Toast.makeText(context, "Empty", Toast.LENGTH_SHORT).show();
}
}
A more elaborate pattern would include broadcast receiver and intents, but I guess this is out of this question's scope.

Loop AsyncTask to fetch JSON and store as object in same list

I want to read and store all JSON values from this api Link with get request "Mini" as example (which is actually an user input variable) and the last number is the page your are viewing. Every page can hold a max of 50 results. The same link is also in XML format (I must read and store as JSON, this is for easier understanding)
In this exmaple there are 8 pages with a total of 359 results. I need to loop through all pages and add all the JSON values to the same object list.
I have the code which work to read one page. I do not know how to make it loop through all pages and add to same object list.
In the acitivty.java onCreate I call the AsyncTask.
String userSearchRequest = search_activity_data.getString("userSearchRequest");
int page = 0;
String spidy_iTN_url = "http://www.gw2spidy.com/api/v0.9/json/item-search/" + userSearchRequest + "/" + page;
itemsByInput_AsyncTask itemsByInput_AsyncTask = new itemsByInput_AsyncTask();
itemsByInput_AsyncTask.setItemListToListings(this);
itemsByInput_AsyncTask.execute(spidy_iTN_url);
This is my AsyncTask class called itemsByInput_AsyncTask.java
import constructors.itemResults_api_constr;
import constructors.itemRoot_api_constr;
public class itemsByInput_AsyncTask extends AsyncTask<String, Void, JSONObject> {
JSONObject Jo_result;
private itemListToListings itemListToListings;
public void setItemListToListings (itemListToListings itemListToListings) {
this.itemListToListings = itemListToListings;
}
#Override
protected JSONObject doInBackground(String... params) {
return spidyHttpGetRequest(params[0]);
}
public JSONObject spidyHttpGetRequest(String URL){
try {
HttpGet get = new HttpGet(URL);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
Jo_result = new JSONObject(result);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return Jo_result;
}
#Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
this.itemListToListings.itemListToListings(JoToJO_constructor(jsonObject));
}
public itemRoot_api_constr JoToJO_constructor(JSONObject Jo_result) {
itemRoot_api_constr spidy_iTN_rootO = new itemRoot_api_constr();
try {
spidy_iTN_rootO.setCount(Jo_result.getInt("count"));
spidy_iTN_rootO.setPage(Jo_result.getInt("page"));
spidy_iTN_rootO.setLast_page(Jo_result.getInt("last_page"));
spidy_iTN_rootO.setTotal(Jo_result.getInt("total"));
JSONArray list = new JSONArray(Jo_result.getString("results"));
for (int i = 0; i < spidy_iTN_rootO.getCount(); i++) {
JSONObject resultsObject = list.getJSONObject(i);
itemResults_api_constr spidy_iTN_resultsO = new itemResults_api_constr();
spidy_iTN_resultsO.setData_id(resultsObject
.getInt("data_id"));
spidy_iTN_resultsO.setName(resultsObject
.getString("name"));
spidy_iTN_resultsO.setRarity(resultsObject
.getInt("rarity"));
spidy_iTN_resultsO.setRestriction_level(resultsObject
.getInt("restriction_level"));
spidy_iTN_resultsO.setImg(resultsObject
.getString("img"));
spidy_iTN_resultsO.setType_id(resultsObject
.getInt("type_id"));
spidy_iTN_resultsO.setSub_type_id(resultsObject
.getInt("sub_type_id"));
spidy_iTN_resultsO.setPrice_last_changed(resultsObject
.getString("price_last_changed"));
spidy_iTN_resultsO.setMax_offer_unit_price(resultsObject
.getInt("max_offer_unit_price"));
spidy_iTN_resultsO.setMin_sale_unit_price(resultsObject
.getInt("min_sale_unit_price"));
spidy_iTN_resultsO.setOffer_availability(resultsObject
.getInt("offer_availability"));
spidy_iTN_resultsO.setSale_availability(resultsObject
.getInt("sale_availability"));
spidy_iTN_resultsO.setSale_price_change_last_hour(resultsObject
.getInt("sale_price_change_last_hour"));
spidy_iTN_resultsO.setOffer_price_change_last_hour(resultsObject
.getInt("offer_price_change_last_hour"));
spidy_iTN_rootO.addObject(spidy_iTN_resultsO);
}
} catch (JSONException e) {
e.printStackTrace();
}
return spidy_iTN_rootO;
}
public interface itemListToListings {
public void itemListToListings(itemRoot_api_constr resultClass);
}
}
And finally in my activity.java i can use my object in the method itemListToListings().
How can I make this loop through all pages (last_page property) and add all JSON values as object in the same list.
EDIT: My itemListToListings function in my activity.
public void itemListToListings(final itemRoot_api_constr spidy_iTN_construct) {
ArrayList<listItemWidgets_constr> image_details = getListData(spidy_iTN_construct);
final ListView lv1 = (ListView) findViewById(R.id.listView);
lv1.setAdapter(new itemListAdapter(this, image_details));
lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
//listItemWidgets_constr newsData = (listItemWidgets_constr) lv1.getItemAtPosition(position);
Toast.makeText(resultsActivity.this, "Selected :" + spidy_iTN_construct.results(position).name, Toast.LENGTH_LONG).show();
Intent i = new Intent(resultsActivity.this, listingsActivity.class);
i.putExtra("itemId", spidy_iTN_construct.results(position).data_id);
startActivity(i);
}
});
}
EDIT 3: error log
05-01 07:17:39.828 3620-3620/com.example.krijn.gw2TP_androidMobile E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.krijn.gw2TP_androidMobile, PID: 3620
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.krijn.gw2TP_androidMobile.AsyncTasks.itemsByInput_AsyncTask$itemListToListings.itemListToListings(com.example.krijn.gw2TP_androidMobile.constructors.itemRoot_api_constr)' on a null object reference
at com.example.krijn.gw2TP_androidMobile.AsyncTasks.itemsByInput_AsyncTask.onProgressUpdate(itemsByInput_AsyncTask.java:88)
at com.example.krijn.gw2TP_androidMobile.AsyncTasks.itemsByInput_AsyncTask.onProgressUpdate(itemsByInput_AsyncTask.java:27)
After I get this error in the Logcat I still see the Log updating with the following in doInBackground
for (int n = 1; n < nPage; n++){
Log.i("gw2Log", "n: " + n);
publishProgress(JoToJO_constructor(spidyHttpGetRequest(makeUrl(n))));
}
After that is done looping the application crashes.
I think you want to make chain calls depending on last_page property you get from the first page. I would do somethig like this where upon each completion of a request the UI is updated on onProgressUpdate
public class itemsByInput_AsyncTask extends AsyncTask<Void, itemRoot_api_constr, Void> {
JSONObject Jo_result;
private itemListToListings itemListToListings;
String userSearchRequest;
public itemsByInput_AsyncTask(String userSearchRequest){
this.userSearchRequest = userSearchRequest;
}
private String makeUrl(int page){
return "http://www.gw2spidy.com/api/v0.9/json/item-search/" +
this.userSearchRequest + "/" + page;
}
#Override
protected Void doInBackground(Void... params) {
itemRoot_api_constr iac;
iac = JoToJO_constructor(spidyHttpGetRequest(makeUrl(0)));
nPage = iac.getLast_page();
publishProgress(iac);
for (int n = 1; n<nPage; n++){
publishProgress(spidyHttpGetRequest(makeUrl(n)));
}
return null;
}
#Override
protected void onProgressUpdate(itemRoot_api_constr... iacs) {
super.onProgressUpdate(iacs);
// assuming method itemListToListings updates UI
// if it doesn't then publishProgress and onProgressUpdate are not needed
// and itemListToListings can be done in doInBackground
this.itemListToListings.itemListToListings(iacs[0]);
}
#Override
protected Void onPostExecute(Void void) {
super.onPostExecute(void);
// unused
}
}
Also:
Adapter, views, and related click listeners should be initiated once. You should move all variables inside of itemListToListings as your Activity field so everytime this callback is called, they won't need to be initiated again.
ListView lv1;
ArrayList<listItemWidgets_constr> image_details = new ArrayList<>();
itemListAdapter adapter;
void onCreate(){
...
lv1 = (ListView) findViewById(R.id.listView);
adapter = new itemListAdapter(this, image_details);
lv1.setOnItemClickListener(...);
}
public void itemListToListings(final itemRoot_api_constr spidy_iTN_construct) {
image_details.clear();
image_details.addAll(getListData(spidy_iTN_construct));
adapter.notifyDataSetChanged();
}

Categories