Issue
I created an app that reads data from url once a button is clicked.
Then, I use this data to display some of it in a new activity.
The url reading is done by using ASynctask as follows:
package com.example.test;
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class Read_URL extends AsyncTask<Void,Void,Void> {
String data = "";
String [] list;
ArrayList <String> hiscore_skill_rank = new ArrayList<>();
ArrayList <String> hiscore_skill_level = new ArrayList<>();
ArrayList <String> hiscore_skill_exp = new ArrayList<>();
@Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL("https://......");
HttpURLConnection httpURLConnection =(HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
for (int j = 0; j <24; j++) {
line = bufferedReader.readLine();
data = data + line;
list = line.split(",");
hiscore_skill_rank.add(list[0]);
hiscore_skill_level.add(list[1]);
hiscore_skill_exp.add(list[2]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
Where the main code is as follows:
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
Button button;
EditText name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.opening_screen);
button = findViewById(R.id.continue_button);
name = findViewById(R.id.username_text);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openHiScore();
}
});
}
public void openHiScore(){
Read_URL process = new Read_URL();
process.execute();
Intent intent = new Intent(this,HiScore.class);
intent.putStringArrayListExtra("hiscore_skill_rank",process.hiscore_skill_rank);
intent.putStringArrayListExtra("hiscore_skill_level",process.hiscore_skill_level);
intent.putStringArrayListExtra("hiscore_skill_exp",process.hiscore_skill_exp);
intent.putExtra("name",name.getText().toString());
startActivity(intent);
}
}
the result from process.execute is 3 arraylists of 24 variables.
My problem is that when I launch the app it crashes however when I launch it in debug mode everything works.
I was thinking maybe since it takes time for the url to read in regular mode it does not know what to display however when in debug mode it has more time to finish obtaining the info from the url.
Is there any reason that reading url can crash an app if it hasnt finished reading the data?
Thank you!
Solution
The problem is with this method:
public void openHiScore(){
Read_URL process = new Read_URL();
process.execute();
Intent intent = new Intent(this,HiScore.class);
intent.putStringArrayListExtra("hiscore_skill_rank",process.hiscore_skill_rank);
intent.putStringArrayListExtra("hiscore_skill_level",process.hiscore_skill_level);
intent.putStringArrayListExtra("hiscore_skill_exp",process.hiscore_skill_exp);
intent.putExtra("name",name.getText().toString());
startActivity(intent);
}
process.execute() is going to start the Async Task, but then immediately move on to creating the new Intent before the doInBackground code has even run. If possible, you should try to move all of the Intent/startActivity code into the onPostEvent of the Read_URL class. Or, create a callback function in your main activity that Read_Url could call from onPostEvent, and that function would do all of the Intent/startActivity stuff back in Main.
Here is an example of how to integrate a callback function. To make it easier, I make Read_URL an internal class defined inside of the MainActivity class.
MainActivity.java
// Imports from MainActivity
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
// Imports from Read_URL
import android.os.AsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
Button button;
EditText name;
public Activity myActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.opening_screen);
button = findViewById(R.id.continue_button);
name = findViewById(R.id.username_text);
myActivity = this;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openHiScore();
}
});
}
public void openHiScore(){
Read_URL process = new Read_URL();
process.execute();
}
public void processResults(ArrayList hiscore_skill_rank, ArrayList hiscore_skill_level, ArrayList hiscore_skill_exp) {
Intent intent = new Intent(this,HiScore.class);
intent.putStringArrayListExtra("hiscore_skill_rank",hiscore_skill_rank);
intent.putStringArrayListExtra("hiscore_skill_level",hiscore_skill_level);
intent.putStringArrayListExtra("hiscore_skill_exp",hiscore_skill_exp);
intent.putExtra("name",name.getText().toString());
startActivity(intent);
}
// I think you can include the Read_URL class inside of your MainActivity class
// In that way, it can access the public variables declared in the MainActivity class
public class Read_URL extends AsyncTask<Void,Void,Void> {
String data = "";
String [] list;
ArrayList <String> hiscore_skill_rank = new ArrayList<>();
ArrayList <String> hiscore_skill_level = new ArrayList<>();
ArrayList <String> hiscore_skill_exp = new ArrayList<>();
@Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL("https://......");
HttpURLConnection httpURLConnection =(HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
for (int j = 0; j <24; j++) {
line = bufferedReader.readLine();
data = data + line;
list = line.split(",");
hiscore_skill_rank.add(list[0]);
hiscore_skill_level.add(list[1]);
hiscore_skill_exp.add(list[2]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
myActivity.processResults(hiscore_skill_rank, hiscore_skill_level, hiscore_skill_exp);
}
} // end of Read_URL
} // end of MainActivity
Answered By - Michael Dougan
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.