Crystallization Δημοσ. 1 Δεκεμβρίου 2015 Δημοσ. 1 Δεκεμβρίου 2015 Καλησπέρα, στα πλαίσια ενός project προσπαθώ να κάνω μια εφαρμογή Android. Το πρόβλημα δημιουργήθηκε όταν πήγα να υλοποιήσω ένα Login / Register και συγκεκριμένα η σύνδεση με την βάση.Χρησιμοποιώ MySQL βάση, PHP πάνω στο domain και API 23 για την εφαρμογή. MySQL βάση:Φτιάχτηκε με phpMyAdmin PHP:Έχει γραφτεί, τεσταριστεί και δουλεύει σωστά. Android APP: Διάβασα κάποια κείμενα για την υλοποίηση της σύνδεσης με HttpClients, αλλά στο API 23 διακόπηκε η υποστήριξη και προστέθηκε το HttpURLConnection.Έγραψα λοιπόν κώδικα που χτυπάει το URL που θέλω, αλλά αυτό που δεν μπορώ να καταφέρω είναι το πέρασμα παραμέτρων μαζί με το request. Γενικά ότι έχει να κάνει με URL Encoding φαίνεται να μην δουλεύει.Ας πιάσουμε λοιπόν το Register, διότι έτσι θα λυθεί και το login. Υπάρχει το activity που ο χρήστης βάζει τα στοιχεία που επιθυμεί και με μια μέθοδο στο onClick του register button καλώ το AsyncTask. register.php (δουλεύει σωστά) <?php //Connects to the database (allagmena) $con = mysqli_connect("to adress tis DB","Username","Password","Database name"); $username = $_POST["username"]; $password = $_POST["password"]; $email = $_POST["email"]; $country = $_POST["country"]; $city = $_POST["city"]; /*Prepares and execute the statement. Values given with mysql injection proofed method */ $statement = mysqli_prepare($con, "INSERT INTO users (username, password, email, country, city) VALUES (?, ?, ?, ?, ?)"); mysqli_stmt_bind_param($statement, "sssss", $username, $password, $email, $country, $city); mysqli_stmt_execute($statement); //Close statement and Database connection mysqli_stmt_close($statement); mysqli_close($con);?> onClick method public void registerUser(View view) { String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); String email = etEmail.getText().toString(); String country = etCountry.getText().toString(); String city = etCity.getText().toString(); User userToRegister = new User(username, password, email, country, city); ServerRequests serverRequest = new ServerRequests(this); serverRequest.storeUserDataInBackgroud(userToRegister, new GetUserCallback() { @Override public void done(User returnedUser) { showLogin(); }}); asyncTask //Stores User's data on the serverpublic User storeUserDataInBackgroud(User userData, GetUserCallback userCallback) { progressDialog.show(); new StoreUserDataAsyncTask(userData, userCallback).execute(); return null;}public class StoreUserDataAsyncTask extends AsyncTask<User,Void,Void> { User user; GetUserCallback userCallback; //StoreUserDataAsyncTask constructor public StoreUserDataAsyncTask(User userData, GetUserCallback userCallback) { this.user = userData; this.userCallback = userCallback; } @Override protected Void doInBackground(User... params) { try{ URL url = new URL(SERVER_ADDRESS + "register.php"); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setReadTimeout(10000); urlConnection.setConnectTimeout(15000); urlConnection.setRequestMethod("POST"); urlConnection.setDoInput(true); urlConnection.setDoOutput(true); HashMap<String,String> dataToSend = new HashMap<>(); dataToSend.put("username", user.username); dataToSend.put("password", user.password); dataToSend.put("email", user.email); dataToSend.put("country", user.country); dataToSend.put("city", user.city); OutputStream os = urlConnection.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os,"UTF-8")); writer.write(getQueryData(dataToSend)); writer.flush(); writer.close(); os.close(); urlConnection.connect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null;} @Override protected void onPostExecute(Void aVoid) { progressDialog.dismiss(); userCallback.done(null); super.onPostExecute(aVoid); }} //Resolve dataToSendpublic static String getQueryData(HashMap<String,String> data) throws UnsupportedEncodingException { //StringBuilder result = new StringBuilder(); //boolean first = true; String result="", and = ""; for(Map.Entry<String,String> entry:data.entrySet()) { /* if (first) { first = false; } else { result.append("&"); result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); result.append("="); result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); } */ result+=and+entry.getKey()+"="+entry.getValue(); if(and.isEmpty())and="&"; } return result;} Κάποια κομμάτια κώδικα που τα έχω σε σχόλια είναι δοκιμές που έκανα και δεν δούλεψαν.Δεν μπορώ να καταλάβω τι κάνω λάθος ή (αν αυτό που έκανα είναι λάθος) ποιος είναι ο σωστός τρόπος να χρησιμοποιήσω το HttpURLConnection για να περάσω παραμέτρους. Οποιαδήποτε βοήθεια είναι ευπρόσδεκτη.
ALLisCHAOS Δημοσ. 2 Δεκεμβρίου 2015 Δημοσ. 2 Δεκεμβρίου 2015 Για πες μας και που χτυπάει και με τι error
Crystallization Δημοσ. 2 Δεκεμβρίου 2015 Μέλος Δημοσ. 2 Δεκεμβρίου 2015 Για πες μας και που χτυπάει και με τι error That's the point, δεν χτυπάει. Καλείτε κανονικά το register.php, απλά δεν κάνει εισαγωγή τίποτα στην βάση γιατί δεν παίρνει κάτι ως _POST από την κλήση. Αντίστοιχα το login, ψάχνει με το query και γυρνάει πίσω τα στοιχεία του user σε JSON, απλά δεν δέχεται παραμέτρους όταν καλείται. Το έχω βάλει εγώ username = "test" και password="123" που υπάρχει ως user στην βάση για να δω αν μου δίνει πίσω σωστά τα δεδομένα και δουλεύει. Όταν είναι να πάρει us/pass από το URL γυρνάει null. Κάτι γίνεται λάθος στο URL Encoding. Δεν καλεί "www.example(.)com/register.php?username=value&password=value" κλπ.. αλλά φαίνεται να καλεί το "www.example(.)com/register.php"
ALLisCHAOS Δημοσ. 3 Δεκεμβρίου 2015 Δημοσ. 3 Δεκεμβρίου 2015 Κάτι γίνεται λάθος στο URL Encoding. Δεν καλεί "www.example(.)com/register.php?username=value&password=value" κλπ.. αλλά φαίνεται να καλεί το "www.example(.)com/register.php" Kάτσε λίγο, εφόσον τα στέλνεις με POST πως περιμένεις να φανούν οι παράμετροι στο url? Εκτός και αν έχω καταλάβει εγώ κάτι λάθος και στο login χρησιμοποιείς GET η οποία στο android όμως ΔΕΝ καλείται όπως έχεις γράψει παραπάνω αλλάζωντας απλά το request method σε "GET" Δηλάδη στο logcat του android studio-eclipse δεν εμφανίζει κάνενα μήνυμα πως κάτι πήγε στραβά? Edit: Οταν είχα ασχοληθεί με παρόμοιο θέμα στο android, το θέμα μου το προκαλούσε για κάποιο λόγο η doInput() οπότε δοκίμασε μία χωρίς αυτήν.
Crystallization Δημοσ. 3 Δεκεμβρίου 2015 Μέλος Δημοσ. 3 Δεκεμβρίου 2015 Kάτσε λίγο, εφόσον τα στέλνεις με POST πως περιμένεις να φανούν οι παράμετροι στο url? Εκτός και αν έχω καταλάβει εγώ κάτι λάθος και στο login χρησιμοποιείς GET η οποία στο android όμως ΔΕΝ καλείται όπως έχεις γράψει παραπάνω αλλάζωντας απλά το request method σε "GET" Δηλάδη στο logcat του android studio-eclipse δεν εμφανίζει κάνενα μήνυμα πως κάτι πήγε στραβά? Edit: Οταν είχα ασχοληθεί με παρόμοιο θέμα στο android, το θέμα μου το προκαλούσε για κάποιο λόγο η doInput() οπότε δοκίμασε μία χωρίς αυτήν. Τι εννοείς για το php κάλεσμα; εγώ υποτίθεται με την μέθοδο getQueryData περνάω παραμέτρους στο string URL. Δεν θα έπρεπε να το κάνω έτσι; Είναι σε φάση: String URL = "http://www.example(.)com/register.php" και του δίνω URL + "?key=value&key=value" και μετά το καλώ. Δεν θα έπρεπε να γίνεται έτσι; Δοκίμασα και χωρίς doInput, τίποτα. Όταν πατάω να γίνει το register το logcat μου βρίσκεται σε αυτή την φάση. 12-03 01:09:25.451 21717-21717/? I/art: Late-enabling -Xcheck:jni 12-03 01:09:25.468 21717-21723/? I/art: Debugger is no longer active 12-03 01:09:25.490 21717-21717/? W/System: ClassLoader referenced unknown path: /data/app/gr.compassbook.snorechat-2/lib/arm 12-03 01:09:25.583 21717-21742/? D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true 12-03 01:09:25.654 21717-21742/? I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: QUALCOMM Build: 09/02/15, 76f806e, Ibddc658e36 12-03 01:09:25.665 21717-21742/? I/OpenGLRenderer: Initialized EGL, version 1.4 12-03 01:09:46.616 21717-21742/gr.compassbook.snorechat E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb3a36cb0 12-03 01:09:46.734 21717-21742/gr.compassbook.snorechat V/RenderScript: 0x9fc32000 Launching thread(s), CPUs 4 To "unknown buffer" το βγάζει πάντα όταν αλλάζω Activity. Δεν μου έχει δημιουργήσει ακόμα πρόβλημα, οπότε δεν το έψαξα παραπάνω. Υ.Γ.: Τώρα είδα την υπογραφή σου. Φοβερή εφαρμογή η ΜΙΧΤ, την χρησιμοποιώ εδώ και καιρό για Wallpaper διότι είμαι φαν του minimal σχεδιασμού του stock Android και θέλω να μην κουράζει το μάτι ένα υπερβολικό wallpaper! 5*
Crystallization Δημοσ. 3 Δεκεμβρίου 2015 Μέλος Δημοσ. 3 Δεκεμβρίου 2015 Λοιπόν, μετά από 6 ώρες debugging χωρίς νόημα βρήκα το "κόλλημα".Άλλαξα όλα τα methods σε "GET" και στα PHP και στα Java files. Και αντί να καλώ το register.php και να περνάω τις παραμέτρους URLEncoded μέσω του OutputStream, το έσβησα και κολλούσα τις URLEncoded παραμέτρους κατευθείαν στο URL.Και το κερασάκι στην τούρτα; Δούλεψε ΜΟΝΟ όταν δεχόμουν το ErrorInputStream (ακόμα και με το doInput() κλειστό) σε μια μεταβλητή ..και ας μην το έκανα τίποτα. Χωρίς αυτό, δεν δούλευε ..το οποίο δεν βγάζει και πολύ νόημα.Αφήνω εδώ τον κώδικα μήπως και κάποια στιγμή τον χρειαστεί κάποιος στο μέλλον. Register.php <?php //Connects to the database (allagmena) $con = mysqli_connect("to adress tis DB","Username","Password","Database name"); $username = $_GET["username"]; $password = $_GET["password"]; $email = $_GET["email"]; $country = $_GET["country"]; $city = $_GET["city"]; /*Prepares and execute the statement. Values given with mysql injection proofed method */ $statement = mysqli_prepare($con, "INSERT INTO users (username, password, email, country, city) VALUES (?, ?, ?, ?, ?)"); mysqli_stmt_bind_param($statement, "sssss", $username, $password, $email, $country, $city); mysqli_stmt_execute($statement); //Close statement and Database connection mysqli_stmt_close($statement); mysqli_close($con);?> onClick public void registerUser(View view) { String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); String email = etEmail.getText().toString(); String country = etCountry.getText().toString(); String city = etCity.getText().toString(); User userToRegister = new User(username, password, email, country, city); ServerRequests serverRequest = new ServerRequests(this); serverRequest.storeUserDataInBackgroud(userToRegister, new GetUserCallback() { @Override public void done(User returnedUser) { showLogin(); }}); asyncTask public class ServerRequests { ProgressDialog progressDialog; public static HttpURLConnection urlConnection; public static final String SERVER_ADDRESS = "http://www.example.gr/"; BufferedReader reader = null; //ServerRequests constructor public ServerRequests (Context context) { progressDialog = new ProgressDialog(context); progressDialog.setCancelable(false); progressDialog.setTitle("Processing"); progressDialog.setMessage("Please wait..."); } //Fetches User's data from the server public User fetchUserDataInBackgroud(User userData, GetUserCallback userCallback) { progressDialog.show(); new FetchUserDataAsyncTask(userData, userCallback).execute(); return null; } //AsyncTask that get User's data from the server public class FetchUserDataAsyncTask extends AsyncTask<Void, Void, User> { User user; GetUserCallback userCallback; //FetchUserDataAsyncTask constructor public FetchUserDataAsyncTask(User userData, GetUserCallback userCallback) { this.user = userData; this.userCallback = userCallback; } @Override protected User doInBackground(Void... params) { User returnedUser = null; HashMap<String,String> dataToSend = new HashMap<>(); dataToSend.put("username", user.username); dataToSend.put("password", user.password); try { URL url = new URL(SERVER_ADDRESS + "fetchUserData.php" + getQueryData(dataToSend)); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setReadTimeout(10000); urlConnection.setConnectTimeout(15000); urlConnection.setRequestMethod("GET"); urlConnection.setDoInput(true); urlConnection.connect(); InputStream is = urlConnection.getInputStream(); reader = new BufferedReader(new InputStreamReader(is)); StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = reader.readLine()) != null) { buffer.append(line); } String result = buffer.toString(); JSONObject jObject = new JSONObject(result); if (jObject.length() != 0) { String username = jObject.getString("username"); String password = jObject.getString("password"); String email = jObject.getString("email"); String country = jObject.getString("country"); String city = jObject.getString("city"); returnedUser = new User(username, password, email, country, city); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); }} return returnedUser;} @Override protected void onPostExecute(User returnedUser) { progressDialog.dismiss(); userCallback.done(returnedUser); super.onPostExecute(returnedUser); }} //Stores User's data on the server public User storeUserDataInBackgroud(User userData, GetUserCallback userCallback) { progressDialog.show(); new StoreUserDataAsyncTask(userData, userCallback).execute(); return null; } public class StoreUserDataAsyncTask extends AsyncTask<User,Void,Void> { User user; GetUserCallback userCallback; //StoreUserDataAsyncTask constructor public StoreUserDataAsyncTask(User userData, GetUserCallback userCallback) { this.user = userData; this.userCallback = userCallback; } @Override protected Void doInBackground(User... params) { HashMap<String,String> dataToSend = new HashMap<>(); dataToSend.put("username", user.username); dataToSend.put("password", user.password); dataToSend.put("email", user.email); dataToSend.put("country", user.country); dataToSend.put("city", user.city); try{ URL url = new URL(SERVER_ADDRESS + "register.php" + getQueryData(dataToSend)); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setReadTimeout(10000); urlConnection.setConnectTimeout(15000); urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestMethod("GET"); urlConnection.setDoOutput(true); urlConnection.connect(); InputStream errors = (urlConnection.getErrorStream()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null;} @Override protected void onPostExecute(Void aVoid) { progressDialog.dismiss(); userCallback.done(null); super.onPostExecute(aVoid); }} //Resolve dataToSend public String getQueryData(HashMap<String,String> data) throws UnsupportedEncodingException { StringBuilder result = new StringBuilder(); boolean first = true; for(Map.Entry<String,String> entry:data.entrySet()) { if (first) { result.append("?"); result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); result.append("="); result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); first = false; } else { result.append("&"); result.append(URLEncoder.encode(entry.getKey(), "UTF-8")); result.append("="); result.append(URLEncoder.encode(entry.getValue(), "UTF-8")); }} return result.toString();}}
Radiant Δημοσ. 3 Δεκεμβρίου 2015 Δημοσ. 3 Δεκεμβρίου 2015 'Όπως λέει και ο ALLisCHAOS μπέρδεψες τa Get και Post requests. Σε κάθε περίπτωση εγώ από τότε που βγήκε ο apache httpclient πήγα σε retrofit(που χρησιμοποιεί την okhttp). Ρίξε μια ματιά, έχει λίγο διάβασμα στην αρχή αλλά θα σου λύσει τα χέρια.
Crystallization Δημοσ. 4 Δεκεμβρίου 2015 Μέλος Δημοσ. 4 Δεκεμβρίου 2015 Έχεις δίκιο, όντως σου λύνει τα χέρια. Δεν το ήξερα, θα το κάνω implement στο Project άσχετα που δούλεψε. Ευχαριστώ.
ALLisCHAOS Δημοσ. 5 Δεκεμβρίου 2015 Δημοσ. 5 Δεκεμβρίου 2015 Τι εννοείς για το php κάλεσμα; εγώ υποτίθεται με την μέθοδο getQueryData περνάω παραμέτρους στο string URL. Δεν θα έπρεπε να το κάνω έτσι; Είναι σε φάση: String URL = "http://www.example(.)com/register.php" και του δίνω URL + "?key=value&key=value" και μετά το καλώ. Δεν θα έπρεπε να γίνεται έτσι; Υ.Γ.: Τώρα είδα την υπογραφή σου. Φοβερή εφαρμογή η ΜΙΧΤ, την χρησιμοποιώ εδώ και καιρό για Wallpaper διότι είμαι φαν του minimal σχεδιασμού του stock Android και θέλω να μην κουράζει το μάτι ένα υπερβολικό wallpaper! 5* Αν και λίγο αργά αλλά... Όταν περνάς παραμέτρους στο URL πχ: www.example.com?p=home&item=one τότε χρησιμοποιείς GET, γενικά ότι παράμετροι φένονται στο url σημαίνει ότι στέλνονται με τη GET, αντίθετα αν χρησιμοποιήσεις τη POST θα δεις πως στο url δε φένεται καμιά παράμετρος. Όπως σωστά έπραξες και κολλάς όπως λες στο url τις παραμέτρους αυτός είναι ο τρόπος για να στείλεις GET request με το android. Δε χρειάζεται τίποτα άλλο απ όσα έγραψες για τη POST. Το έκανες να δουλέψει και αρχικά αυτό έχει σημασία απλά να έχεις στα υπόψη σου, ότι γενικά απ όσο έχω δει, όταν θέλουμε να ρωτήσουμε κάτι το server χρησιμοποιούμε GET, και όταν θέλουμε να κάνουμε κάτι update/νέα εγγραφή τη POST ( πιο συγκεκριμένα για new τη PUT). Oπότε καλό θα ήταν να κάνεις το register να δουλέψει με τη POST. Μπορείς να χρησιμοποιήσεις και το retrofit όπως είπε ο @Radiant ίσως σε βολέψει περισσότερο. BTW χαίρομαι που σου άρεσε το Mixt
Crystallization Δημοσ. 8 Δεκεμβρίου 2015 Μέλος Δημοσ. 8 Δεκεμβρίου 2015 Αν και λίγο αργά αλλά... Όταν περνάς παραμέτρους στο URL πχ: www.example.com?p=home&item=one τότε χρησιμοποιείς GET, γενικά ότι παράμετροι φένονται στο url σημαίνει ότι στέλνονται με τη GET, αντίθετα αν χρησιμοποιήσεις τη POST θα δεις πως στο url δε φένεται καμιά παράμετρος. Όπως σωστά έπραξες και κολλάς όπως λες στο url τις παραμέτρους αυτός είναι ο τρόπος για να στείλεις GET request με το android. Δε χρειάζεται τίποτα άλλο απ όσα έγραψες για τη POST. Το έκανες να δουλέψει και αρχικά αυτό έχει σημασία απλά να έχεις στα υπόψη σου, ότι γενικά απ όσο έχω δει, όταν θέλουμε να ρωτήσουμε κάτι το server χρησιμοποιούμε GET, και όταν θέλουμε να κάνουμε κάτι update/νέα εγγραφή τη POST ( πιο συγκεκριμένα για new τη PUT). Oπότε καλό θα ήταν να κάνεις το register να δουλέψει με τη POST. Μπορείς να χρησιμοποιήσεις και το retrofit όπως είπε ο @Radiant ίσως σε βολέψει περισσότερο. Το έβαλα ήδη το Retrofit στο Project και δεν με έχει βολέψει μόνο, μου έλυσε τα χέρια! Τα update / register γίνονται με POST για λόγους ασφαλείας; BTW χαίρομαι που σου άρεσε το Mixt Μετράει 1
@_zerocool Δημοσ. 12 Δεκεμβρίου 2015 Δημοσ. 12 Δεκεμβρίου 2015 'Όπως λέει και ο ALLisCHAOS μπέρδεψες τa Get και Post requests. Σε κάθε περίπτωση εγώ από τότε που βγήκε ο apache httpclient πήγα σε retrofit(που χρησιμοποιεί την okhttp). Ρίξε μια ματιά, έχει λίγο διάβασμα στην αρχή αλλά θα σου λύσει τα χέρια. Έχεις δοκιμάσει να τρέξεις από το retofit 2 to call.enque σε controller class και να κάνει update το UI?
Radiant Δημοσ. 13 Δεκεμβρίου 2015 Δημοσ. 13 Δεκεμβρίου 2015 Έχεις δοκιμάσει να τρέξεις από το retofit 2 to call.enque σε controller class και να κάνει update το UI? Ναι κανονικά. Είχες κάποιο πρόβλημα;
@_zerocool Δημοσ. 13 Δεκεμβρίου 2015 Δημοσ. 13 Δεκεμβρίου 2015 Ναι κανονικά. Είχες κάποιο πρόβλημα; Έχω το παρακάτω και κάνω ενα call στο github. Θέλω όλο αυτό να το κάνω refactoring να έχω ενδιάμεσα controller o οποίος να επιστρέφει το reponse.body() και αυτό να το πάω όπου θέλω στο UI για να το δείχνω. Αυτό που έκανα στο github όταν έβαζα simple_list_view χτιπούσε γιατί ήταν null (Λογικό) το έλυσα με recycler view απλά γενικώς θέλνω να δώ ποιο είναι το best practice σε τέτοιες καταστάσεις. https://github.com/renegens/example-android-challenge
Radiant Δημοσ. 14 Δεκεμβρίου 2015 Δημοσ. 14 Δεκεμβρίου 2015 Έχω το παρακάτω και κάνω ενα call στο github. Θέλω όλο αυτό να το κάνω refactoring να έχω ενδιάμεσα controller o οποίος να επιστρέφει το reponse.body() και αυτό να το πάω όπου θέλω στο UI για να το δείχνω. Αυτό που έκανα στο github όταν έβαζα simple_list_view χτιπούσε γιατί ήταν null (Λογικό) το έλυσα με recycler view απλά γενικώς θέλνω να δώ ποιο είναι το best practice σε τέτοιες καταστάσεις. https://github.com/renegens/example-android-challenge Το πρώτο που μου έρχεται στο μυαλό είναι να χρησιμοποιήσεις ένα callbacκ για να κάνεις update το UI. Δημιουργείς ένα controller class που διαχειρίζεται το networking, ας το πούμε NetworkingController. Δημιουργείς ένα interface που κάνουν implement οι Activities ή τα fragment σου που θα περιλαμβάνουν networking, ας το πούμε NetworkingResponseListener. Το NetworkingResponseListener θα περιλαμβάνει μια μέθοδο(το callback) με την οποία θα κάνεις update το εκάστοτε UI όταν λάβεις το async response από το retrofit. Aς πούμε τη μέθοδο αυτή onUpdateUi(). Για να το κάνεις αυτό βέβαια πρέπει να περνάς στον constructor του NetworkingController ένα reference του NetworkingResponseListener. Σου παραθέτω ένα πολύ πρόχειρο παράδειγμα για το project που linkαρες: NetworkingController.java public class NetworkingController { private NetworkingResponseListener listener; public interface NetworkingResponseListener { void onUpdateUi(List<CommitCollection> responseBody); } public NetworkingController(NetworkingResponseListener listener) { this.listener = listener; } public void fetchGithubCommits(){ Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); // prepare call in Retrofit 2.0 GithubAPI githubAPI = retrofit.create(GithubAPI.class); Call<List<CommitCollection>> call = githubAPI.getCommits(); call.enqueue(new Callback<List<CommitCollection>>() { @Override public void onResponse(Response<List<CommitCollection>> response, Retrofit retrofit) { listener.onUpdateUi(response.body()); } @Override public void onFailure(Throwable t) { t.printStackTrace(); } }); } } MainActivity.java public class MainActivity extends AppCompatActivity implements NetworkingController.NetworkingResponseListener{ ... @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); setSupportActionBar(toolbar); recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); NetworkingController controller = new NetworkingController(this); controller.fetchGithubCommits(); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null) .show(); }}); } ... @Override public void onUpdateUi(List<CommitCollection> responseBody) { ListAdapter listAdapter = new ListAdapter(responseBody); String size = String.valueOf(responseBody.size()); Log.i(TAG, size); String name = responseBody.get(0).getCommit().getAuthor().getName(); Log.i(TAG, name); recyclerView.setAdapter(listAdapter); } } ps1: Ούτως ή άλλως καλό θα ήταν να απομονώσεις την υλοποίηση του networking από τα Views(Activities). Τη MainActivity δε θα πρεπε να την απασχολεί αν χρησιμοποιείς retrofit, volley ή ξερό HttpUrlConnection. Πάνω σε αυτό δες ένα βιντεάκι: Google I/O 2010 - Android REST client applications ps2: Φυσικά όλο αυτό παίρνει κιάααλλο refactoring. Μια καλή βιβλιοθήκη για dependecny injections είναι το dagger από την square καθώς και το dagger2 από την google. ps3: Όλα αυτά είναι σχετικά καινούρια και για μένα οπότε αυτά που παραθέτω-γράφω δεν είναι απαραίτητα best practise
@_zerocool Δημοσ. 14 Δεκεμβρίου 2015 Δημοσ. 14 Δεκεμβρίου 2015 Είσαι ωραίος, θα σου στείλω αύριο μερικά links για αυτά που λες και να το κάνω implement και να το καταλάβω. Στο ψάξιμο είμαι και εγώ για clean architecture. Δες πρώτα αυτά τα δυο που μου έχουν βοηθήσει, ειδικά τα podcast. http://fragmentedpodcast.com/ https://medium.com/@theMikhail/take-command-of-android-development-9411af8cf571#.mmr82o8wv 1
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα