How to achieve this?
Okay I have this process
On Index Activity, when I click the side nav Profile, it will call Fragment (Profile) thru Fragment Transaction
if (id == R.id.nav_profile){
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.setCustomAnimations(R.anim.enter,R.anim.exit,R.anim.enter,R.anim.exit);
transaction.replace(R.id.flContent, new Profile(), "ProfileFragment");
transaction.addToBackStack(null);
viewPager.getAdapter().notifyDataSetChanged();
transaction.commit();
}
Now I'm on the Profile Fragment:
When I click "Apply for Developer" button, it will call DevRegistration activity by Intent
case 1:
btnBeDeveloper.setText("Apply for Developer");
btnBeDeveloper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent index = new Intent(getActivity(), DevRegistration.class);
startActivity(index);
}
});
break;
Step 3:
On DevRegistration after I click Register, it will display a dialog fragment
FragmentManager fm = getSupportFragmentManager();
df_SuccessDevRegistration dialogFragment = new df_SuccessDevRegistration();
dialogFragment.show(fm, "Dev Register.");
Now this is my Dialog Fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
View rootView = inflater.inflate(R.layout.fragment_success_developer_registration, container, false);
btnDevGoProfile = (Button) rootView.findViewById(R.id.btnDevGoProfile);
btnDevGoProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
getActivity().finish();
}
});
return rootView;
}
Now my problem is, when I press the button on the dialog fragment, it should refresh my profile fragment. how to achieve that? I tried detach attach but my app just crashed and for null exception.
public class Profile extends Fragment {
TextView txvStudID, txvStudUsername, txvStudEmail, txvStudBday,txvProfileName;
CollapsingToolbarLayout ctlName;
ImageView imvProfilePic;
Button btnBeDeveloper;
View rootView;
String picURL;
FragmentTransaction ft; Fragment currentFragment;
/** Recycler View**/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rootView = inflater.inflate(R.layout.activity_profile, container, false);
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.profile_toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
getFragmentManager().popBackStack();
navigationView.getMenu().getItem(0).setChecked(true);
}
});
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setHomeButtonEnabled(true);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(true);
txvStudID = (TextView) rootView.findViewById(R.id.txvStudID);
txvStudUsername = (TextView) rootView.findViewById(R.id.txvStudUsername);
txvStudEmail = (TextView)rootView.findViewById(R.id.txvStudEmail);
txvStudBday = (TextView) rootView.findViewById(R.id.txvStudBday);
txvProfileName = (TextView) rootView.findViewById(R.id.txvProfileName);
ctlName = (CollapsingToolbarLayout) rootView.findViewById(R.id.ctlName);
imvProfilePic = (ImageView) rootView.findViewById(R.id.imvProfilePic);
btnBeDeveloper = (Button) rootView.findViewById(R.id.btnBeDeveloper);
checkLevelOfAccess();
/** get user's data **/
getCurrentUserData(DataClass.currentEnteredUsername);
return rootView;
}
public void checkLevelOfAccess()
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String acctID = preferences.getString("acctID", "DEFAULT");
switch (checkLevelOfAccess(acctID)) {
// if the level of access is developer
case 1:
btnBeDeveloper.setText("Developer Console");
btnBeDeveloper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent index = new Intent(getActivity(), UploadApp.class);
startActivity(index);
}
});
break;
// else if the level of access is not a developer
case 0:
switch (checkIfRegistered(acctID))
{
//already apply
case 0:
btnBeDeveloper.setText("Cancel Developer Request");
break;
case 1:
btnBeDeveloper.setText("Apply for Developer");
btnBeDeveloper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent index = new Intent(getActivity(), DevRegistration.class);
startActivityForResult(index, 10001);
}
});
break;
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if ((requestCode == 10001) && (resultCode == Activity.RESULT_OK))
{
System.out.println("IM HERE NA!!!");
checkLevelOfAccess();
}
}
public void getCurrentUserData(String currentUser) {
try {
String accountURL = DataClass.localAddress + "android_php/account.php";
URL url = new URL(accountURL);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("users");
for (int x = 0; x < parentArray.length(); x++) {
JSONObject finalObject = parentArray.getJSONObject(x);
if (finalObject.getString("username").equalsIgnoreCase(currentUser) || finalObject.getString("studID").equalsIgnoreCase(currentUser)
|| finalObject.getString("email").equalsIgnoreCase(currentUser)) {
txvStudID.setText(finalObject.getString("studID"));
txvStudUsername.setText(finalObject.getString("username"));
txvStudEmail.setText(finalObject.getString("email"));
txvStudBday.setText(convertDate(finalObject.getString("bday")));
ctlName.setTitle(finalObject.getString("name"));
txvProfileName.setText(finalObject.getString("name"));
//set Profile Picture
picURL = DataClass.localAddress + finalObject.getString("pic");
LoadImageFromURL loadImage = new LoadImageFromURL();
loadImage.execute();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String convertDate(String date) throws ParseException {
String strCurrentDate = date;
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
DateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
Date parseDate = inputFormat.parse(strCurrentDate);
String converted = outputFormat.format(parseDate);
return converted;
}
public class LoadImageFromURL extends AsyncTask<String, Void, Bitmap>{
#Override
protected Bitmap doInBackground(String... params) {
// TODO Auto-generated method stub
try {
InputStream is = new URL(picURL).openConnection().getInputStream();
Bitmap bitMap = BitmapFactory.decodeStream(is);
GetCircleBitmap gcb = new GetCircleBitmap();
Bitmap b = gcb.GetCircleBitmap(bitMap);
return b;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
imvProfilePic.setImageBitmap(result);
}
}
public int checkLevelOfAccess(String data)
{
try {
String accountURL = DataClass.localAddress + "android_php/account.php";
URL url = new URL(accountURL);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("users");
for (int x = 0; x < parentArray.length(); x++) {
JSONObject finalObject = parentArray.getJSONObject(x);
// true
if (finalObject.getString("acctid").equalsIgnoreCase(data) && finalObject.getString("acctlofa").equals("1"))
{
return 1;
}
else if (finalObject.getString("acctid").equalsIgnoreCase(data) && finalObject.getString("acctlofa").equals("0"))
{
return 0;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return 2;
}
/** Check if the user already applied to become a developer **/
public int checkIfRegistered(String data) {
try {
String accountURL = DataClass.localAddress + "android_php/developer_account.php";
URL url = new URL(accountURL);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("users");
for (int x = 0; x < parentArray.length(); x++) {
JSONObject finalObject = parentArray.getJSONObject(x);
// pending application
if (finalObject.getString("acctID").equalsIgnoreCase(data) && finalObject.getString("devStatus").equals("0"))
{
return 0;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
}
I'dd suggest you using intents between activity call, and StartForRsults().
Then when your activity resume using public void onActivityResult(int requestCode, int resultCode, Intent intent) you'll be able to check if the user correctly registered (and not cancelled registration) through a boolead in the intent.
Then, set a global variable "refreshProfile", and make it true when your activity resume with the correct intent saying user registered. Override public void onPostResume(), use a if statement to check wether or not you need to refresh the profile. If yes, do so then make the variable false. if not, do nothing.
Doing so will prevent you from updating your profileFragment when activity is resuming wich can cause some crash sometimes ("IllegalStateException: Can not perform this action after onSaveInstanceState") because you are updating the UI at the wrong moment.
Other option consists into changing the dialogFragment, setting a custom function to refresh your activity.
build.setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
/*refresh profile here
with instruction like getActivity().refresh();
where refresh is your activity public function to refresh profile.
*/
}
});
However, i dislike that way because your profile will wait user to confirm before being updated. I find it more clearer and elegant to have profile updated THEN prevent the user everything went fine. But personnal opinion here.
In your fragment that you need to refresh create and register a broadcast receiver.
When you want to refresh the fragment (in your case when clicking the button on the dialog fragment) send a broadcast which will be caught by your broadcast receiver on the profile fragment.
This will also make sure that the solution is not too tightly coupled.
You need to return the result back to the activity which contains the profile data. This can be done in several ways. In this case, I assume you want the profile to remain changed permanently. For example if the user quits the app and starts it again a week later, the changes should persist to the profile screen. This suggests that you need the data to be stored permanently. For small amounts of data, such as a boolean flag or a String, you can use SharedPreferences. For more complex data, use a SQLite database or a flat file. Now the dialog just saves the data to the chosen medium and the profile fragment loads the data in onCreate().
Related
I created app that takes JSON with AsyncTask from server. When User click a button app starts new Activity and download data from server and show it as a items in ListView. The Problem is when I open new Activity it takes too long to load. When button is pressed app freeze on about one or two seconds and then show black screen for another 2/3 seconds. After that activity is displayed but it is very slow. It freeze every time user is scrolling or pressing button to display more options of custom adapter. Is there any way to make app more smooth? Json data that is downloaded is just simple JSONArray with JSONObjects that has 2 string values and one HTML format. This 3 values is display to user.
Part of Custom Adapter class
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
SuggestionList suggestionList = getItem(position);
int actualPosition = 0;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.sugestion_list, parent, false);
}
final Button suggestionsButton = (Button) convertView.findViewById(R.id.suggestionsMore);
final TextView suggestionNumber = (TextView) convertView.findViewById(R.id.sugestionNumber);
final TextView suggestionDescription = (TextView) convertView.findViewById(R.id.suggestionDescription);
final ImageView bio = convertView.findViewById(R.id.sugestionBio);
final ImageView block = convertView.findViewById(R.id.sugestionBlock);
final ImageView call = convertView.findViewById(R.id.sugestionCall);
...
final Animation slideUp = AnimationUtils.loadAnimation(getContext(), R.anim.slideup);
final Animation slideDown = AnimationUtils.loadAnimation(getContext(), R.anim.slidedown);
final Handler handler = new Handler();
suggestionsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (bioSuggestions.getVisibility() == View.GONE) {
bio.setVisibility(View.VISIBLE);
block.setVisibility(View.VISIBLE);
call.setVisibility(View.VISIBLE);
bioSuggestions.startAnimation(slideUp);
blockSuggestions.startAnimation(slideUp);
callSuggestions.startAnimation(slideUp);
} else if (bioSuggestions.getVisibility() == View.VISIBLE) {
bioSuggestions.startAnimation(slideDown);
blockSuggestions.startAnimation(slideDown);
callSuggestions.startAnimation(slideDown);
handler.postDelayed(new Runnable() {
#Override
public void run() {
bio.setVisibility(View.GONE);
block.setVisibility(View.GONE);
call.setVisibility(View.GONE);
}
}, 300);
}
}
});
if (actualPosition != position) {
if (bio.getVisibility() == View.VISIBLE) {
bio.setVisibility(View.GONE);
block.setVisibility(View.GONE);
call.setVisibility(View.GONE);
}
actualPosition = position;
}
JSONObject jsonValSuggestions = new getSugestions().sugestionsDetails(position, "suggestions");
try {
final String name = jsonValSuggestions.getString("client_name");
final String num = jsonValSuggestions.getString("client_number");
final String description = jsonValSuggestions.getString("client_description");
bio.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent suggestionsDetails = new Intent(view.getContext(), SuggestionsDetails.class);
suggestionsDetails.putExtra("client_number", num);
suggestionsDetails.putExtra("client_name", name);
suggestionsDetails.putExtra("client_description", description);
activity.startActivityForResult(suggestionsDetails, position);
}
});
block.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent suggestionBlock = new Intent(view.getContext(), BlockSuggestionsActivity.class);
activity.startActivity(suggestionBlock);
}
});
call.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent suggestionCall = new Intent(view.getContext(), CallSuggestionActivity.class);
suggestionCall.putExtra("client_number", num);
suggestionCall.putExtra("client_name", name);
activity.startActivity(suggestionCall);
}
});
} catch (Exception e) {
e.printStackTrace();
}
try {
if (suggestionList.suggestionName.equals("null") || suggestionList.suggestionName.equals("")) {
suggestionNumber.setText(suggestionList.suggestionNumber);
} else {
suggestionNumber.setText(suggestionList.suggestionName);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
suggestionDescription.setText(Html.fromHtml(suggestionList.suggestionDescription, Html.FROM_HTML_MODE_LEGACY));
} else {
suggestionDescription.setText(Html.fromHtml(suggestionList.suggestionDescription));
}
} catch (Exception e) {
Log.i("exception", e.getMessage());
}
return convertView;
}
Part of AsyncTask class
public static final String REQUEST_METHOD = "GET";
public static final int READ_TIMEOUT = 15000;
public static final int CONNECTION_TIMEOUT = 15000;
#Override
protected String doInBackground(String... params) {
String clientUrl = params[0];
String result;
String inputLine;
JSONObject obj;
String data;
String message;
try {
URL myUrl = new URL(clientUrl);
HttpURLConnection connection = (HttpURLConnection) myUrl.openConnection();
connection.setRequestMethod(REQUEST_METHOD);
connection.setReadTimeout(READ_TIMEOUT);
connection.setConnectTimeout(CONNECTION_TIMEOUT);
connection.connect();
InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
StringBuilder stringBuilder = new StringBuilder();
while ((inputLine = reader.readLine()) != null) {
stringBuilder.append(inputLine);
}
reader.close();
streamReader.close();
result = stringBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
result = null;
}
return result;
}
public String[] getSuggestionsList() {
String[] suggestionList = new String[5];
String result;
String status;
JSONObject listObj;
String suggestionsData;
JSONObject suggestionsDataObj;
JSONArray suggestionsDataArr;
String ClientsSugestionsUrl = "https://example.com/token=" + authToken;
getApiClientSugestions getSugestionsFromApi = new getApiClientSugestions();
try {
result = getSugestionsFromApi.execute(ClientsSugestionsUrl).get();
try {
listObj = new JSONObject(result);
status = listObj.getString("result");
suggestionsData = listObj.getString("suggestions");
suggestionsDataArr = new JSONArray(suggestionsData);
} catch (Exception e) {
e.printStackTrace();
suggestionsDataArr = null;
status = null;
}
suggestionList[3] = status;
suggestionList[4] = suggestionsDataArr.toString();
} catch (Exception e) {
e.printStackTrace();
}
return suggestionList;
}
Activity
public class CallsSuggestionsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calls_suggestions);
Slidr.attach(this);
getSupportActionBar().setTitle("Skontaktuj siÄ™");
}
#Override
protected void onResume() {
super.onResume();
CallsSuggestionList();
}
public void CallsSuggestionList() {
final ListView suggestionList = findViewById(R.id.sugestionList);
final ArrayList<SuggestionList> suggestionArray = new ArrayList<SuggestionList>();
SuggestionListAdapter suggestionListAdapter = new SuggestionListAdapter(getContext(), suggestionArray, this);
String[] suggestionListArray = new getSugestions().getSuggestionsList();
String suggStat = suggestionListArray[3];
String arrayList = suggestionListArray[4];
String clientName;
String clientNumber;
String clientDescription;
try {
JSONArray jsonArray = new JSONArray(arrayList);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject explrObject = jsonArray.getJSONObject(i);
clientName = explrObject.getString("client_name");
clientNumber = explrObject.getString("client_number");
clientDescription = explrObject.getString("client_description");
if (suggStat.equals("true")) {
SuggestionList suggestionList1 = new SuggestionList(clientName, clientDescription, clientNumber);
suggestionListAdapter.addAll(suggestionList1);
suggestionListAdapter.notifyDataSetChanged();
suggestionList.setAdapter(suggestionListAdapter);
}
}
} catch (Exception e) {
Log.i("exception", e.getMessage());
e.printStackTrace();
clientName = null;
clientDescription = null;
clientNumber = null;
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
SuggestionList
public class SuggestionList {
public String suggestionNumber;
public String suggestionDescription;
public String suggestionCallType;
public String suggestionName;
public SuggestionList(
// String suggestionCallType,
String suggestionName, String suggestionDescription, String suggestionNumber) {
this.suggestionNumber = suggestionNumber;
// this.suggestionCallType = suggestionCallType;
this.suggestionName = suggestionName;
this.suggestionDescription = suggestionDescription;
}
}
Adapter are custom with custom view displayed to user. I use similar custom adapter to show content from sqlite that is on phone and there app isn't so slow. But when I open this activity it slow down dramatically. Also I noticed when I press back button it take very long to back to previous screen.
The problem is in the getSuggestionsList function. in this function, you are calling getSugestionsFromApi.execute(ClientsSugestionsUrl).get(); which make your code sync again. I mean your code is waiting this code to be executed.
One way (not right way, but easy way): you can call new getSugestions().getSuggestionsList(); in a new thread.
Second way, call getSugestionsFromApi.execute(ClientsSugestionsUrl) without get() function. But to get result of the code, you need to give an interface.
To get right usage: https://xelsoft.wordpress.com/2014/11/28/asynctask-implementation-using-callback-interface/
So I'm going to post the simple code to a program I'm writing. Here is my question. I think I'm connecting to my server just fine (Because I'm posting this online I will replace the server address with a fake one) and I want to know if I'm actually sending the variables to the server. I am sending the data to a PHP server using this string ("?systemid=demo&pwd=demo&reason=do%20something&qnumber=A36"). This is hard-coded for testing purposes. My question is, am I actually sending the data? There doesn't seem to be a send() method. Please excuse my ignorance. I'm new to Android.
My thought was that when I write to the OutputStream, I am also sending the data. Please take a look
public class PrintTicketActivity extends AppCompatActivity {
private static final String TAG2 = "PrintTicketActivity";
Context mContext;
Button mButtonA, mButtonB, mButtonC, mButtonD, mButtonE, mButtonF;
List<Button> mButtons;
List<PrintJob> mPrintJobs;
WebView mWebView;
int printJobNum = 1;
// here i'm initializing the variables with an arbitrary value so the compiler won't complain
// that they may have not been initialized in the button's onclick listeners
// these values are overwritten from sharedPreferences anyway.....the file will always exist unless there is a major problem
int numA, numB, numC, numD, numE, numF;
String buttonA, buttonB, buttonC, buttonD, buttonE, buttonF;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_print_ticket);
mContext = this;
mButtons = new ArrayList<>();
mPrintJobs = new ArrayList<>();
mButtonA = (Button) findViewById(R.id.button_a);
mButtonB = (Button) findViewById(R.id.button_b);
mButtonC = (Button) findViewById(R.id.button_c);
mButtonD = (Button) findViewById(R.id.button_d);
mButtonE = (Button) findViewById(R.id.button_e);
mButtonF = (Button) findViewById(R.id.button_f);
// add the buttons to the list so we can check later to see if any of the buttons has empty text
// and then hide the button if it is empty
mButtons.add(mButtonA);
mButtons.add(mButtonB);
mButtons.add(mButtonC);
mButtons.add(mButtonD);
mButtons.add(mButtonE);
mButtons.add(mButtonF);
// check for the start up file
File file = new File("data/data/com.myDomain.myProgram/shared_prefs/start.xml");
if (file.exists()) {
// place text from preferences on the buttons
updateUI();
} else {
Toast.makeText(mContext, "Something went wrong", Toast.LENGTH_SHORT).show();
}
mButtonA.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_A, numA, "A", mButtonA);
new SendQueueToServer().execute();
}
});
mButtonB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_B, numB, "B", mButtonB);
}
});
mButtonC.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_C, numC, "C", mButtonC);
}
});
mButtonD.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_D, numD, "D", mButtonD);
}
});
mButtonE.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_E, numE, "E", mButtonE);
}
});
mButtonF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executeQueue(NUMBER_F, numF, "F", mButtonF);
}
});
}
private void executeQueue(String prefKey, int num, String category, Button button) {
printTicket(button.getText().toString(), category + num);
// increment the number after printing the ticket
++num;
// update the number in the shared preferences
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS, MODE_PRIVATE).edit();
editor.putInt(prefKey, num);
editor.apply();
// update the UI to get an updated version of the queue number
updateUI();
}
private void updateUI() {
SharedPreferences preferences = getSharedPreferences(MY_PREFS, MODE_PRIVATE);
buttonA = preferences.getString(A, "");
buttonB = preferences.getString(B, "");
buttonC = preferences.getString(C, "");
buttonD = preferences.getString(D, "");
buttonE = preferences.getString(E, "");
buttonF = preferences.getString(F, "");
numA = preferences.getInt(NUMBER_A, 1);
numB = preferences.getInt(NUMBER_B, 1);
numC = preferences.getInt(NUMBER_C, 1);
numD = preferences.getInt(NUMBER_D, 1);
numE = preferences.getInt(NUMBER_E, 1);
numF = preferences.getInt(NUMBER_F, 1);
mButtonA.setText(buttonA);
mButtonB.setText(buttonB);
mButtonC.setText(buttonC);
mButtonD.setText(buttonD);
mButtonE.setText(buttonE);
mButtonF.setText(buttonF);
// if a button doesn't have anything assigned to it, hide the button
for (Button button : mButtons) {
if (button.getText().equals("")) {
button.setVisibility(View.GONE);
}
}
}
private void printTicket(String queueTitle, String queueCategory) {
// create a WebView object for printing
WebView webView = new WebView(mContext);
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
#Override
public void onPageFinished(WebView view, String url) {
Log.i(TAG2, "page finished loading " + url);
createWebPrintJob(view);
mWebView = null;
}
});
String html = "<html><body><h2 style=\"text-align:center;font-size:60px\">" + queueTitle + "</h2><h1 style=\"text-align:center" +
";font-size:200px\">" +
queueCategory + "</h1>";
webView.loadDataWithBaseURL(null, html, "text/HTML", "UTF-8", null);
// Keep a reference to WebView object until you pass the PrintDocumentAdapter
// to the PrintManager
mWebView = webView;
}
#SuppressWarnings("deprecation")
private void createWebPrintJob(WebView webView) {
PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
// Get a print adapter instance
PrintDocumentAdapter printAdapter;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
printAdapter = webView.createPrintDocumentAdapter("print_job_num" + printJobNum);
printJobNum++;
} else {
printAdapter = webView.createPrintDocumentAdapter();
printJobNum++;
}
// Create a print job with name and adapter instance
String jobName = getString(R.string.app_name) + " Document";
PrintJob printJob = printManager.print(jobName, printAdapter,
new PrintAttributes.Builder().build());
// save for status checking later
mPrintJobs.add(printJob);
}
#Override
protected void onResume() {
super.onResume();
updateUI();
}
// #Override
// public void onBackPressed() {
// // don't add superclass constructor
// // I am disabling the back button here
// }
private class SendQueueToServer extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
OutputStream out = null;
String urlParameters = "?systemid=demo&pwd=demo&reason=do%20something&qnumber=A36";
HttpsURLConnection connection = null;
try {
URL url = new URL("https://www.example.com/php");
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.connect();
out = new DataOutputStream(connection.getOutputStream());
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(out, "UTF-8"));
writer.write(urlParameters);
writer.flush();
writer.close();
Log.d(TAG2, " and the response is: " + connection.getResponseMessage());
Log.d(TAG2, "you are connected and good to go");
} catch (IOException e) {
e.printStackTrace();
} finally {
assert connection != null;
connection.disconnect();
}
return null;
}
}
}
The url parameters indicates that you are trying to make a GET request and this is not proper procedure to make an HTTP GET request. You don't need to write anything to the OutputStreamWriter if you are making a GET request. Here's a template for the same:
URL url;
HttpURLConnection urlConnection = null;
String urlParameters = "?systemid=demo&pwd=demo&reason=do%20something&qnumber=A36";
try {
url = new URL("https://www.example.com/php"+urlParameters);
urlConnection = (HttpURLConnection) url
.openConnection();
//use this block of code in case you are looking for some response from your server
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
char current = (char) data;
data = isw.read();
System.out.print(current);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
You can use Retrofit Library to send data to Server. It's very easy to communicate with Server using this library.
Visit http://square.github.io/retrofit/ for tutorial on how to use this library in Android/Java.
I'm developing a Calorie app using an API Database. When the user clicks the search button it gets the string and then searches the database. For some reason the user edit text "string" is not being retrieved therefore not being able to search the api database. When I did the debug I noticed that the string is "" meaning empty.
Thanks again so much, New to api and android studio.
public class AddEntry extends Fragment implements View.OnClickListener {
EditText FoodET,CalorieET;
ImageButton Savebtn, Cancelbtn;
Button searchbutton;
String foodET,calorieET;
//database
private DatabaseHandler dba;
public AddEntry() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View myView = inflater.inflate(R.layout.fragment_add_entry, container,
false);
Savebtn = (ImageButton) myView.findViewById(R.id.SaveBtn);
Savebtn.setBackgroundColor(Color.TRANSPARENT);
Savebtn.setOnClickListener(this);
searchbutton = (Button) myView.findViewById(R.id.SearchButton);
searchbutton.setOnClickListener(this);
Cancelbtn = (ImageButton) myView.findViewById(R.id.CancelBtn);
Cancelbtn.setBackgroundColor(Color.TRANSPARENT);
Cancelbtn.setOnClickListener(this);
return myView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FoodET= (EditText)view.findViewById(R.id.foodEditText);
FoodET.setInputType(InputType.TYPE_CLASS_TEXT);
CalorieET=(EditText)view.findViewById(R.id.caloriesEditText);
CalorieET.setInputType(InputType.TYPE_CLASS_NUMBER);
foodET = ((EditText)
view.findViewById(R.id.foodEditText)).getText().toString();
foodET.isEmpty();
FoodET.setText("");
CalorieET.setText("");
calorieET = ((EditText)
view.findViewById(R.id.caloriesEditText)).getText().toString();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.SearchButton:
FoodSearch search = new FoodSearch(foodET, CalorieET );
search.execute();
break;
case R.id.SaveBtn:
if (FoodET.getText().toString().equals(null) ||
CalorieET.getText().toString().equals(null)||
CalorieET.getText().toString().equals("") ||
CalorieET.getText().toString().equals("")){
Toast.makeText(getActivity(), "Please enter information",
Toast.LENGTH_LONG).show();
AlertDialog NotFound = new
AlertDialog.Builder(getContext()).create();
NotFound.setTitle("Error");
NotFound.setMessage("Food not found :(");
NotFound.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int
which) {
dialog.dismiss();
}
});
}
else
((appMain) getActivity()).loadSelection(0);
break;
case R.id.CancelBtn:
// EditText descriptionET=
(EditText)getView().findViewById(R.id.foodEditText);
//descriptionET.setText("");
//EditText calorieET=
(EditText)getView().findViewById(R.id.caloriesEditText);
//calorieET.setText("");
((appMain) getActivity()).loadSelection(0);
break;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDetach() {
super.onDetach();
}
private class FoodSearch extends AsyncTask<Void, Void, String> {
String food;
EditText calories;
FoodSearch(String food, EditText calories){
this.food = food;
this.calories = calories;
}
#Override
protected String doInBackground(Void... params) {
try {
food = food.replaceAll(" ", "%20");
URL url = new URL("http://api.nal.usda.gov/ndb/search/?
format=JSON&q=" + food +
"&max=1&offset=0&sort=r&api_
key=xMJV33vSmKsquFqcBwZ23oJ7DlL2abmfsrDUUx1l");
HttpURLConnection urlConnection = (HttpURLConnection)
url.openConnection();
try {
BufferedReader bufferedReader = new BufferedReader(new
InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
String result = stringBuilder.toString();
if(result.contains("zero results")) {
String s = "empty";
return s;
}
JSONObject object = (JSONObject) new
JSONTokener(result).nextValue();
JSONObject list = object.getJSONObject("list");
JSONArray items = list.getJSONArray("item");
String item = items.get(0).toString();
int i = item.indexOf("ndbno\":\"") + 8;
int f = item.indexOf("\"", i);
String ndbno = item.substring(i,f);
Log.d("DEBUG", ndbno);
URL url2 = new URL("http://api.nal.usda.gov/ndb/reports/?
ndbno=" + ndbno +
"&type=b&format=JSON&api_
key=xMJV33vSmKsquFqcBwZ23oJ7DlL2abmfsrDUUx1l");
HttpURLConnection urlConnection2 = (HttpURLConnection)
url2.openConnection();
BufferedReader bufferedReader2 = new BufferedReader(new
InputStreamReader(urlConnection2.getInputStream()));
StringBuilder stringBuilder2 = new StringBuilder();
String line2;
while ((line2 = bufferedReader2.readLine()) != null) {
stringBuilder2.append(line2).append("\n");
}
bufferedReader2.close();
String res = stringBuilder2.toString();
int index = res.indexOf("\"unit\": \"kcal\",") + 46;
int index2 = res.indexOf("\"", index);
String calories = res.substring(index,index2);
urlConnection2.disconnect();
return calories;
}
finally{
urlConnection.disconnect();
}
}
catch(Exception e) {
Log.e("ERROR", e.getMessage(), e);
String s = "empty";
return s;
}
}
protected void onPostExecute(String response) {
if(!response.isEmpty() && !response.equals("empty")) {
calories.setText(response);
} else {
AlertDialog foodNotFound = new
AlertDialog.Builder(getContext()).create();
foodNotFound.setTitle("Error");
foodNotFound.setMessage("Food not found :(");
foodNotFound.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int
which) {
dialog.dismiss();
}
});
}
}
}
}
Try this
case R.id.SearchButton:
String foodEtString=FoodET.getText().toString();
FoodSearch search = new FoodSearch(foodEtString, CalorieET );
search.execute();
break;
And Add this in onCreate as well
FoodET= (EditText)view.findViewById(R.id.foodEditText);
FoodET.setInputType(InputType.TYPE_CLASS_TEXT);
CalorieET=(EditText)view.findViewById(R.id.caloriesEditText);
CalorieET.setInputType(InputType.TYPE_CLASS_NUMBER);
Use these values instead when you go to execute the AsyncTask
String FoodName = FoodET.getText().toString().trim();
String calString = CalorieET.getText().toString().trim();
The following values are always empty when the view is created (and are not necessary in your code).
foodET = ((EditText) view.findViewById(R.id.foodEditText)).getText().toString();
calorieET = ((EditText) view.findViewById(R.id.caloriesEditText)).getText().toString();
So that explains why this didn't work
FoodSearch search = new FoodSearch(foodET, CalorieET );
You should always try to call getText in response to a user event in order to get the most recent value(s) of the input fields
I'd also suggest that you learn how to properly parse JSON data (don't use indexOf), or go so far as look into the Retrofit library
This is my code to save the gridview scroll state. But it is not retrieved in the restore instance. Only this step is required for my project to pass.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){
rootView = inflater.inflate(R.layout.fragment_movies, null);
if (savedInstance != null) {
MovieTask.mProgressDialog.onRestoreInstanceState(savedInstance);
gridView.smoothScrollToPosition(savedInstance.getInt("scroll"));
}
setHasOptionsMenu(true);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
MovieTask.mProgressDialog.onSaveInstanceState();
savedInstanceState.putInt("scroll",gridView.getFirstVisiblePosition());
super.onSaveInstanceState(savedInstanceState);
}
Here is the AsyncTask code. Where I am initializing the gridview.
#Override
protected void onPreExecute(){
mProgressDialog = new ProgressDialog(mContext);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
String categoryType = preferences.getString(mContext.getString(R.string.pref_key_category) ,mContext.getString(R.string.pref_category_default_value));
if(categoryType.equals(Constants.TOP_RATED_KEY)){
Category = Constants.TOP_RATED_KEY;
mProgressDialog.setTitle("Top Rated Movies");
} else if (categoryType.equals(Constants.POPULARITY_KEY)){
Category = Constants.POPULARITY_KEY;
mProgressDialog.setTitle("Popular Movies");
}
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected String[] doInBackground(String... strings) {
try {
URL url = new URL(Constants.MOVIE_URL + Category + Constants.API_KEY);
Log.d(LOG_TAG, String.valueOf(url));
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
try {
return getMovieDataFromJson(movieJsonStr);
} catch (JSONException e) {
Log.d(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] result){
if(result != null) {
mProgressDialog.dismiss();
if(NetworkUtility.isOnline(mContext)){
List<Model> favoriteMovie = Model.listAll(Model.class);
MovieAdapter movieAdapter = new MovieAdapter(mContext, favoriteMovie, new MovieAdapter.Callback() {
#Override
public void onItemSelected(String title, String poster, String plot, double ratings, String release, long id) {
if (MainActivity.mTwoPane) {
((FragmentActivity)mContext).getSupportFragmentManager().beginTransaction()
.replace(R.id.details_fragment_container, DetailsFragment.newInstance(title, poster, plot, ratings, release, id))
.commit();
} else {
Intent intent = new Intent(mContext, DetailsActivity.class);
intent.putExtra("title", title);
intent.putExtra("poster", poster);
intent.putExtra("plot",plot);
intent.putExtra("ratings", ratings);
intent.putExtra("release", release);
intent.putExtra("id", id);
mContext.startActivity(intent);
}
}
});
MoviesFragment.gridView = (GridView) MoviesFragment.rootView.findViewById(R.id.grid_view);
MoviesFragment.gridView.setAdapter(movieAdapter);
int index = MoviesFragment.gridView.getFirstVisiblePosition();
MoviesFragment.gridView.smoothScrollToPosition(index);
} else {
Toast.makeText(mContext,"Please Enable Internet Services",Toast.LENGTH_SHORT).show();
}
}
}
Do you use to shared preference Otherway try it
gridView.setSelection(savedInstance.getInt("scroll"))
Do you know when onSaveInstanceState and onRestoreInstanceStatewill be called. If you manually close the activity, for example hit back, the savedInstance will always be null.
I think you are looking for sharedPreference to store the scroll position
At the following point during the execution of onCreateView(), it looks like the AsyncTask has been started (at least you're accessing MovieTask.mProgressDialog and nothing crashes, so I think onPreExecute() has finished successfully).
MovieTask.mProgressDialog.onRestoreInstanceState(savedInstance);
gridView.smoothScrollToPosition(savedInstance.getInt("scroll"));
If onPostExecute() runs after these lines are executed, then the following statements will simply set the scroll position to the beginning of the content:
MoviesFragment.gridView.setAdapter(movieAdapter);
int index = MoviesFragment.gridView.getFirstVisiblePosition();
MoviesFragment.gridView.smoothScrollToPosition(index);
This happens because movieAdapteris created from scratch and the GridView is informed that from now on the content to display will be provided by this adapter. So the usual thing happens: getCount() is called, the GridView is filled from the beginning and the scroll position is set to the beginning as well.
To get the desired scroll position, you can introduce a variable
int lastScrollPosition = -1;
in MovieTask. Set the value to the desired position in onCreateView() if the savedInstanceState != null
int index = savedInstance.getInt("scroll", -1);
// case 1: AsyncTask still busy
MovieTask.lastScrollPosition = index;
// case 2: AsyncTask already finished
if (index >= 0)
{
// seems from the source of AbsListView = parent of GridView
// that there will be no crash if index is too big
MoviesFragment.gridView.smoothScrollToPosition(index);
}
and read it in onPostExecute():
if (lastScrollPosition >= 0 and lastScrollPosition < movieAdapter.getCount())
{
MoviesFragment.gridView.smoothScrollToPosition(lastScrollPosition);
}
This way, the scroll position will be used if possible.
I am writing an app to pull movie data from the MovieDB api and display the information in a GridView.
When the app first loads I would expect the view to populate initially, but it does not. I have a sort option in the menu bar and when the sort option is set the first time the GridView is populated by movies in order of popularity, as it should initially, but regardless of what sort criteria is actually selected.
I have used the logs to determine that the correct data is being retrieved from the API and being processed properly, so I have to assume that the adapter is not updating the view properly.
Why isn't the view showing initially or updating as it should?
FilmFragment.java:
public class FilmFragment extends Fragment {
private ArrayList<FilmParcelable> filmParcels = new ArrayList<FilmParcelable>();
private ImageAdaptor mFilmAdaptor;
protected String[] sortOptions = {
"popularity.desc",
"vote_average.desc"
};
protected String sortBy = sortOptions[0];
private final String LOG_TAG = FilmFragment.class.getSimpleName();
public FilmFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if (savedInstanceState == null || !savedInstanceState.containsKey("films")){
updateFilms();
mFilmAdaptor = new ImageAdaptor(getActivity(),filmParcels);
} else {
filmParcels = savedInstanceState.getParcelableArrayList("films");
mFilmAdaptor = new ImageAdaptor(getActivity(),filmParcels);
}
// allow fragment to handle menu events
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.filmfragment, menu);
}
public boolean onOptionsItemSelected(MenuItem item){
//Handle action bar item clicks. The action bar will
//automatically handle clicks on the Home/Up button, so long
//as you specify a parent activity in AndroidManifest.xml
int id = item.getItemId();
if (id == R.id.action_sort){
showSortDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onSaveInstanceState(Bundle outState){
outState.putParcelableArrayList("films", filmParcels);
super.onSaveInstanceState(outState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Find GridView to populate with poster images
GridView gridView = (GridView) rootView.findViewById(R.id.gridView);
// Set the adaptor of the GridView to my ImageAdaptor
gridView.setAdapter(mFilmAdaptor);
updateAdaptor();
return rootView;
}
// Update movie data in case there is a change in the "sort by" option
// Or the fragment is started with no saved data
public void updateFilms(){
new FetchFilmTask().execute();
}
public void updateAdaptor(){
mFilmAdaptor.clear();
mFilmAdaptor.addAll(filmParcels);
mFilmAdaptor.notifyDataSetChanged();
}
// Show dialog sort pop up
public void showSortDialog(){
DialogFragment dialog = new SortDialog();
dialog.setTargetFragment(this, 0);
dialog.show(getActivity().getSupportFragmentManager(), "SortDialog");
}
// If a fragment or activity called by this fragment returns to this fragment,
// Get the information returned via the intent
public void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == 0){
int mSelected = data.getIntExtra("Selected Option", -1);
if (mSelected != -1){
sortBy = sortOptions[mSelected];
updateFilms();
updateAdaptor();
}
}
}
// Class to get JSON data from The Movie Database API
public class FetchFilmTask extends AsyncTask<Void, Void, FilmParcelable[]> {
private final String LOG_TAG = FetchFilmTask.class.getSimpleName();
private final String MOVIE_DB_API_KEY = "e1968ef8ba074d7d5bf07a59de8b2310";
protected FilmParcelable[] doInBackground(Void... params){
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain raw JSON response as a string
String movieDBStr = null;
try {
// Construct URL for Movie DB query
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority("api.themoviedb.org")
.appendPath("3")
.appendPath("discover")
.appendPath("movie")
.appendQueryParameter("api_key", MOVIE_DB_API_KEY)
.appendQueryParameter("sort_by", sortBy);
String myUrl = builder.build().toString();
Log.d(LOG_TAG, myUrl);
URL url = new URL(myUrl);
// Create the request to The Movie DB, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null){
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
movieDBStr = buffer.toString();
} catch (IOException e){
Log.e(LOG_TAG, "Error: ", e);
return null;
} finally {
if (urlConnection != null){
urlConnection.disconnect();
}
if (reader != null){
try{
reader.close();
} catch (final IOException e){
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getFilmDataFromJson(movieDBStr);
} catch (JSONException e){
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private FilmParcelable[] getFilmDataFromJson(String movieDBStr)
throws JSONException {
// JSON objects that need to be extracted
final String MDB_RESULTS = "results";
final String MDB_ID = "id";
final String MDB_SYNOPSIS = "overview";
final String MDB_RELEASE = "release_date";
final String MDB_POSTER = "poster_path";
final String MDB_TITLE = "title";
final String MDB_RATING = "vote_average";
JSONObject filmJson = new JSONObject(movieDBStr);
JSONArray filmArray = filmJson.getJSONArray(MDB_RESULTS);
FilmParcelable[] resultFilms = new FilmParcelable[filmArray.length()];
for (int i = 0; i < filmArray.length(); i++){
// Data needed by the FilmParcelable
int id;
String title;
String releaseDate;
String posterUrl;
Double voteAverage;
String plotSynopsis;
JSONObject film = filmArray.getJSONObject(i);
id = film.getInt(MDB_ID);
plotSynopsis = film.getString(MDB_SYNOPSIS);
releaseDate = film.getString(MDB_RELEASE);
posterUrl = "http://image.tmdb.org/t/p/w300" + film.getString(MDB_POSTER);
title = film.getString(MDB_TITLE);
voteAverage = film.getDouble(MDB_RATING);
Log.d(LOG_TAG, title);
Log.d(LOG_TAG, posterUrl);
resultFilms[i] = new FilmParcelable(id, title, releaseDate, posterUrl, voteAverage, plotSynopsis);
}
return resultFilms;
}
#Override
protected void onPostExecute(FilmParcelable[] result){
if (result != null){
filmParcels = new ArrayList<>(Arrays.asList(result));
}
}
}
}
ImageAdaptor.java:
public class ImageAdaptor extends ArrayAdapter<FilmParcelable> {
public ImageAdaptor(Activity context, ArrayList<FilmParcelable> filmParcels){
super(context, 0, filmParcels);
}
public View getView(int position, View convertView, ViewGroup parent){
Context context= getContext();
View gridView;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String mUrl = getItem(position).getUrl();
if (convertView == null) {
gridView = inflater.inflate(R.layout.gridview_film_layout, parent, false);
// Find the image view from the gridview_film_layout
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
// Set the image view to contain image located at mUrl
Picasso.with(getContext()).load(mUrl).into(posterView);
} else {
gridView = convertView;
}
return gridView;
}
}
accordingly to the code you posted you are returning over and over the same cell of your GridView. You should have those two lines
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
Picasso.with(getContext()).load(mUrl).into(posterView);
out of the if/else guard:
if (convertView == null) {
// inflate
} else {
// gridView = convertView;
}
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
Picasso.with(getContext()).load(mUrl).into(posterView);
return gridView;
I was attempting to update the adapter after populating the arraylist used for the adapter. However the arraylist was populated and updated in the background so the code:
updateFilms();
updateAdaptor();
was causing the adaptor to update before the data had completed loading in the background.
After fixing that Blackbelt's solution was correct.