Getting errors when parsing values - java

I'm getting errors when i'm trying to parse the datas.
The program is to retrieve the datas from database and parse it to the main menu where the RecycleView lists out the datas such as name,username,image and description.
I'm following this tutorial https://www.youtube.com/watch?v=g30Q9KHubTU
This is the code with errors.
DataParser.java
public class DataParser extends AsyncTask<Void,Void,Boolean> { //<<<line 22
Context c;
String jsonData;
RecyclerView rv;
ProgressDialog pd;
ArrayList<Item> items = new ArrayList<>();
public DataParser(Context c, String jsonData, RecyclerView rv) {
this.c = c;
this.jsonData = jsonData;
this.rv = rv;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(c);
pd.setTitle("Parse");
pd.setMessage("Parsing...Please wait.");
pd.show();
}
#Override
protected Boolean doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
pd.dismiss();
if(success) //<<<line 59
{
//bind
MyAdapter adapter = new MyAdapter(c,items);
rv.setAdapter(adapter);
}
else
{
Toast.makeText(c, "Unable to parse", Toast.LENGTH_SHORT).show();
}
}
private Boolean parseData()
{
try
{
JSONArray ja = new JSONArray(jsonData);
JSONObject jo;
items.clear();
Item item;
for(int i = 0; i<ja.length();i++)
{
jo=ja.getJSONObject(i);
int itemid = jo.getInt("itemid");
String imagepath = jo.getString("imagepath");
String itemname = jo.getString("itemname");
String username = jo.getString("username");
String itemdesc = jo.getString("itemdesc");
item = new Item();
item.setId(itemid);
item.setItemname(itemname);
item.setUsername(username);
item.setItemdesc(itemdesc);
item.setImagepath(imagepath);
items.add(item);
}
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
}
These are the errors
java.lang.NullPointerException:
Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
at chengweifeng1132701116.fyp.m_MySQL.DataParser.onPostExecute(DataParser.java:59)
at chengweifeng1132701116.fyp.m_MySQL.DataParser.onPostExecute(DataParser.java:22)

This is because you are always returning null from doInBackground. So, your success variable is always null in onPostExecute(). Have the appropriate logic for parsing inside doInBackground and based on whether it was successful or not, return true or false.

Related

Populating TextView after Spinner Selection

I'm Having difficulty populating TextViews from my SQL Database. I have one column populating a spinner and then I want the Two Textviews to be populated by MySQL Columns from the same row of the spinner selection.
I cannot find the correct code to add to the OnSelectedItem portion.
MainActivity.java
public class MainActivity extends AppCompatActivity implements OnItemSelectedListener{
Context c;
TextView colorDensity;
Spinner colorSpinner= findViewById(R.id.colorSpinner);
ArrayList<String> colors=new ArrayList<>();
final static String urlAddress = "http://www.burtkuntzhandjobs.org/dbcolors.php";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Downloader(MainActivity.this,urlAddress,colorSpinner).execute();
colorDensity = (TextView)findViewById(R.id.colorDensity);
colorSpinner.setOnItemSelectedListener(this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(this,"Select Color", Toast.LENGTH_SHORT).show();
}
}
DataParser.java
public class DataParser extends AsyncTask<Void,Void,Integer> {
Context c;
Spinner colorSpinner;
String jsonData;
ProgressDialog pd;
ArrayList<String> colors=new ArrayList<>();
public DataParser(Context c, Spinner colorSpinner, String jsonData) {
this.c = c;
this.colorSpinner = colorSpinner;
this.jsonData = jsonData;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(c);
pd.setTitle("Parse");
pd.setMessage("Parsing");
pd.show();
}
#Override
protected Integer doInBackground(Void...params) {
return this.parseData();
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
pd.dismiss();
if(result == 0){
Toast.makeText(c,"Unable to Parse",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(c,"Parse Successful",Toast.LENGTH_SHORT).show();
ArrayAdapter adapter = new ArrayAdapter(c,android.R.layout.simple_list_item_1,colors);
colorSpinner.setAdapter(adapter);
}
}
private int parseData() {
try {
JSONArray ja=new JSONArray(jsonData);
JSONObject jo=null;
colors.clear();
Colors s=null;
for (int i = 0; i < ja.length(); i++) {
jo = ja.getJSONObject(i);
int ui = jo.getInt("ui");
String color=jo.getString("color");
String density = jo.getString("density");
String strainer = jo.getString("strainer");
s = new Colors();
s.setIu(ui);
s.setColor(color);
s.setDensity(density);
s.setStrainer(strainer);
colors.add(color);
}
return 3;
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
}
Downloader.java
public class Downloader extends AsyncTask<Void,Void,String> {
Context c;
String urlAddress;
Spinner colorSpinner;
ProgressDialog pd;
public Downloader(Context c, String urlAddress, Spinner colorSpinner) {
this.c = c;
this.urlAddress = urlAddress;
this.colorSpinner = colorSpinner;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(c);
pd.setTitle("Fetch");
pd.setMessage("Fetching");
pd.show();
}
#Override
protected String doInBackground(Void...params) {
return this.downloadData();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pd.dismiss();
if(s == null) {
Toast.makeText(c,"Unable to Retrieve",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(c,"Success",Toast.LENGTH_SHORT).show();
DataParser parser=new DataParser(c,colorSpinner,s);
parser.execute();
}
}
private String downloadData() {
HttpURLConnection con= (HttpURLConnection) Connector.connect(urlAddress);
if(con == null) {
return null;
}
InputStream is = null;
try {
is = new BufferedInputStream(con.getInputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String line = null;
StringBuffer response=new StringBuffer();
if(br != null){
while ((line=br.readLine()) !=null) {
response.append(line+"\n");
}
br.close();
} else {
return null;
}
return response.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(is != null){
try{
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
Make following changes & add required code,
1. Remove Spinner colorSpinner= findViewById(R.id.colorSpinner); from class variable.
2. Add Spinner colorSpinner= findViewById(R.id.colorSpinner); in onCreate` method.
Look this spinet,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner);
Spinner colorSpinner= findViewById(R.id.colorSpinner);
new Downloader(this, urlAddress,colorSpinner).execute();
colorDensity = (TextView)findViewById(R.id.colorDensity);
colorSpinner.setOnItemSelectedListener(this);
}
3. Access colors list from DataParser class,
public class DataParser extends AsyncTask<Void,Void,Integer> {
Context c;
Spinner colorSpinner;
String jsonData;
ProgressDialog pd;
ArrayList<String> colors=new ArrayList<>();
private static ArrayList<Colors> colorsList=new ArrayList<>(); // add this line
public DataParser(Context c, Spinner colorSpinner, String jsonData) {
this.c = c;
this.colorSpinner = colorSpinner;
this.jsonData = jsonData;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(c);
pd.setTitle("Parse");
pd.setMessage("Parsing");
pd.show();
}
#Override
protected Integer doInBackground(Void...params) {
return this.parseData();
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
pd.dismiss();
if(result == 0){
Toast.makeText(c,"Unable to Parse",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(c,"Parse Successful",Toast.LENGTH_SHORT).show();
ArrayAdapter adapter = new ArrayAdapter(c,android.R.layout.simple_list_item_1,colors);
colorSpinner.setAdapter(adapter);
}
}
private int parseData() {
try {
JSONArray ja=new JSONArray(jsonData);
JSONObject jo=null;
colors.clear();
Colors s=null;
for (int i = 0; i < ja.length(); i++) {
jo = ja.getJSONObject(i);
int ui = jo.getInt("ui");
String color=jo.getString("color");
String density = jo.getString("density");
String strainer = jo.getString("strainer");
s = new Colors();
s.setUi(ui);
s.setColor(color);
s.setDensity(density);
s.setStrainer(strainer);
colors.add(color);
colorsList.add(s); // add this line
}
return 3;
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
public static List<Colors> getColorsList() { // add this method
return colorsList;
}
}
4. Set density accordingly in onItemSelected() method of activity class.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
List<Colors> colorsList = DataParser.getColorsList();
colorDensity.setText(colorsList.get(position).getDensity());
}

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.

Endless RecyclerView with Asynctask using EndlessRecyclerOnScrollListener

I have an activity which searches for a query (using async task and server side PHP) and gives out a list in recycler view, Now i want to implement endless/infinite scrolling when user reaches bottom. I have tried to do that using EndlessScrollListener. There are two problems i need help with.
first, the new list recreates itself instead of appending to the old list.
second, the current_page int variable keeps its value from the previous search and scroll, means when running AsyncTask for second time, the current_page int variable still retains the value from the first time and does not reset.
public class MainActivity extends AppCompatActivity {
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private RecyclerView mRVFish;
private AdapterFish mAdapter;
private LinearLayoutManager mLayoutManager;
private String searchQuery;
SearchView searchView = null;
private String query;
private EndlessRecyclerOnScrollListener mScrollListener = null;
private SwipeRefreshLayout mSwipeRefreshLayout = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRVFish = (RecyclerView) findViewById(R.id.fishPriceList);
mLayoutManager = new LinearLayoutManager(MainActivity.this);
mRVFish.setLayoutManager(mLayoutManager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// adds item to action bar
getMenuInflater().inflate(R.menu.search_main, menu);
// Get Search item from action bar and Get Search service
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
searchView.setIconified(false);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
// Every time when you press search button on keypad an Activity is recreated which in turn calls this function
#Override
protected void onNewIntent(Intent intent) {
// Get search query and create object of class AsyncFetch
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
query = intent.getStringExtra(SearchManager.QUERY);
if (searchView != null) {
searchView.clearFocus();
}
int startrow =0;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
mScrollListener = new EndlessRecyclerOnScrollListener(mLayoutManager) {
#Override
public void onLoadMore(int current_page) {
int startrow=current_page;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
}
};
mRVFish.addOnScrollListener(mScrollListener);
// enable pull down to refresh
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
int startrow =0;
String type="";
String filetype="";
AsyncFetch myTask = new AsyncFetch(query, startrow, type, filetype);
myTask.execute();
// after refresh is done, remember to call the following code
if (mSwipeRefreshLayout != null && mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false); // This hides the spinner
}
}
});
}
}
// Create class AsyncFetch
private class AsyncFetch extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(MainActivity.this);
HttpURLConnection conn;
URL url = null;
String searchQuery;
int startrow;
String type;
String filetype;
public AsyncFetch(String searchQuery, int startrow, String type, String filetype){
this.searchQuery=searchQuery;
this.startrow = startrow;
this.type = type;
this.filetype=filetype;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your php file resides
url = new URL("http://someurl/json/search.php");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("POST");
// setDoInput and setDoOutput to true as we send and recieve data
conn.setDoInput(true);
conn.setDoOutput(true);
// add parameter to our above url
Uri.Builder builder = new Uri.Builder().appendQueryParameter("searchQuery", searchQuery).appendQueryParameter("startrow", String.valueOf(startrow));
String query = builder.build().getEncodedQuery();
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(query);
writer.flush();
writer.close();
os.close();
conn.connect();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return("Connection error");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
pdLoading.dismiss();
List<DataFish> data=new ArrayList<>();
pdLoading.dismiss();
if(result.equals("no rows")) {
Toast.makeText(MainActivity.this, "No Results found for entered query", Toast.LENGTH_LONG).show();
}else{
try {
JSONArray jArray = new JSONArray(result);
// Extract data from json and store into ArrayList as class objects
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
DataFish fishData = new DataFish();
try {
fishData.fileName = URLDecoder.decode(json_data.getString("file"), "UTF-8");
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
fishData.fileName=json_data.getString("file");
}
fishData.linkName = json_data.getString("link");
fishData.reg_date = json_data.getString("reg_date");
fishData.fileSize = json_data.getString("filesize");
data.add(fishData);
}
mAdapter = new AdapterFish(MainActivity.this, data);
mRVFish.setAdapter(mAdapter);
if(jArray.length()>19)
mScrollListener.setLoading(false);
else
mScrollListener.setLoading(true);
} catch (JSONException e) {
// You to understand what actually error is and handle it appropriately
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
Toast.makeText(MainActivity.this, result.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
}
EndlessRecyclerOnScrollListener.java
public abstract class EndlessRecyclerOnScrollListener extends
RecyclerView.OnScrollListener {
public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = false; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 0; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 20;
private LinearLayoutManager mLayoutManager;
public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView mRVFish, int dx, int dy) {
super.onScrolled(mRVFish, dx, dy);
if(dy < 0) {
return;
}
// check for scroll down only
visibleItemCount = mRVFish.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
// to make sure only one onLoadMore is triggered
synchronized (this) {
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached, Do something
current_page=current_page+20;
onLoadMore(current_page);
loading = true;
}
}
}
public void setLoading(boolean loading) {
this.loading = loading;
}
public abstract void onLoadMore(int current_page);
}
first, the new list recreates itself instead of appending to the old list.
If you set a new adapter you swap the content of the recycler view. I think you do it in the following code
mAdapter = new AdapterFish(MainActivity.this, data);
mRVFish.setAdapter(mAdapter);
To append the data you need to add new elements to the adapter's dataset (dataset where you get data to bind views in your adapter) and then call adapter.notifyDataSetChanged() or better adapter.notifyItemRangeInserted(int positionStart, int itemCount)
There are also a number of tools to optimize adding the elements, like DiffUtil
second, the current_page int variable keeps its value from the previous search and scroll, means when running AsyncTask for second time
Not sure what was library developer's idea here, but the easiest way would be to just create a method in the EndlessRecyclerOnScrollListener similar to:
public void resetPage() {
current_page = 20;
}
And call it before invoking new search.

ProgressDialog in AsyncTask in Fragment crashes

I have a Fragment with AsyncTask inside an Activity. But i get this exception when i run the search:
Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference.
It has something to do with the Fragment not knowing if the Activity is running, but i don't know how to fix it.
Please help.
Here is the code:
class Send_API extends AsyncTask<String, Void, String> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
if (movieList != null){
movieList.clear();
adapter.notifyDataSetChanged();
}
dialog = new ProgressDialog(getActivity());
dialog.setMessage("Searching...");
dialog.show();
}
#Override
protected String doInBackground(String... params) {
String queryString = null;
try {
queryString = "" +
"s=" + URLEncoder.encode(txt, "utf-8");
} catch (UnsupportedEncodingException e) {
}
return HttpHandler.get(params[0], queryString);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
dialog.dismiss();
if (result == null) {
Toast.makeText(getActivity(), "error getting results...", Toast.LENGTH_LONG).show();
} else {
try {
JSONObject json = new JSONObject(result);
JSONArray searchArray = json.getJSONArray("Search");
for (int i = 0; i < searchArray.length(); i++) {
JSONObject searchObject = searchArray.getJSONObject(i);
String title = searchObject.getString("Title");
String type = searchObject.getString("Type");
String year = searchObject.getString("Year");
String imdbID = searchObject.getString("imdbID");
String poster_url = searchObject.getString("Poster");
movieList.add(new Movie(title, type, year, imdbID, poster_url));
Log.e(TAG, "MovieList is " + movieList);
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "error parsing results...", Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
}
}
}
dialog = new ProgressDialog(getActivity());
getActivity() will return null when you're initializing your Fragment. You'll have to wait until onAttach() in the fragment lifecycle for it to return non-null.
That's the reason for the NPE.
Overall, don't have non-default constructors in fragments. Set up the fragment view only in onCreateView().
Try to pass base context to your asynctask and replace getActivity() with it or getApplicationContext()

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