mtiplab06 - 2017 - 2018 - pdf - r2.pdf · dr predrag pecev – mobilne tehnologije i programiranje...
TRANSCRIPT
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
1
MOBILNE TEHNOLOGIJE I PROGRAMIRANJE –
MTIPLAB06
Vežba 6 – GSON, AsyncTask Callbacks, Progress Dialogs, povezivanje sa
REST servisom
UVOD
U okviru ove vežbe biće dorađena MTIP Studenti Android aplikacija koja je formirana u
prethodnoj vežbi (MTIPLab05). Dorada spomenute aplikacije se odnosi na dodavanje GSON
biblioteke (Google open source biblioteka za serijalizaciju i deserijalizaciju Java objekata i/u JSON
format, komunikaciju sa REST servisom putem AsyncTask Callback-ova uz čekanje na izvršavanje
spomenute komunikacije u kombinaciji sa Progress Dialogom. Takđe biće formirani adapteri za
odgovarajuće kontrolere kako bi se podaci koji se preuzmu od REST servisa mogli prikazati
unutar spomenute aplikacije.
GSON
GSON je open source biblioteka za serijalizaciju i deserijalizaciju Java objekata i/u JSON format i
izvorni kod iste se može preuzeti sa https://github.com/google/gson Za potrebe ovog projekta,
pristupiće se kompajliranoj verziji iste u formi *.jar arhive putem Maven Central-a. Aktuelna
verzija spomenute biblioteke u trenutku formiranja ove vežbe je 2.8.2 i repozitorijum spomenute
verzije se nalazi na linku http://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.2/
Slika broj 1. MTIP Studenti u Project perspektivi i libs folder
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
2
Slika broj 2. Kopiranje gson-2.8.2.jar arhive u libs folder
Slika broj 3. Add to Library Slika broj 4. Create Library
Potrebno je preuzeti fajl gson-2.8.2.jar, promeniti perspektivu MTIP Studenti rešenja na Project
i otvoriti libs folder kao što je to prikazano na slici broj 1. Zatim je potrebno prekopirati fajl gson-
2.8.2.jar u libs folder kao što je to prikazano na slici broj 2, i dodati spomenutu arhivu u formi
biblioteke modulu App. Desnim klikom na arhivu gson-2.8.2.jar prikazuje se meni koji je
prikazan na slici broj 3, dok se izborom stavke Add to Library prikazuje dijalog Create Library
koji je prikazan na slici broj 4.
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
3
PRISTUP INTERNETU I POMOĆNE KLASE ZA RAD SA HTTP
ZAHTEVIMA
Android je specifična platforma i zasniva se na sistemu dozvola za upotrebu određenih sistema.
Konkretno, ukoliko neka aplikacija treba da koristi usluge skladištenja prostora na SD kartici,
navedena aplikacija treba i da je zatraži unutar manifesta iste. Pošto MTIP Studenti Android
aplikacija koristi usluge REST servisa koji se nalazi na nekom računaru (idealno na internetu
povezano sa nekim domenom radi lakšeg poziva) unutar AndroidManifest.xml fajla potrebno je
dodati sledeću liniju koda kako bi spomenuta aplikacija imala pristup internetu putem
odgovarajućih protokola (HTTP).
<uses-permission android:name="android.permission.INTERNET" />
Listing broj 1. Pristup internetu (linuju koda smestiti unutar AndroidManifest.xml fajla)
U listingu koda broj 2 je klasa MTIPShared koju treba oformiti unutar paketa rs.tfzr.data.
Spomenuta klasa sadrži jednu statičku promenljivu tipa String koja ukazuje na osnovnu putanju
do REST servisa koja MTIP Studenti android aplikacija koristi. Pošto Android kao operativni
sistem poseduje loopback adresu localhost i 127.0.0.1, URL adrese koje koriste navedene pozive
se ne mogu koristiti čak iako se aplikacija izvršava unutar emulatora i REST servis se nalazi na
istom računaru. Dakle ako se navede adresa koja u sebi sadrži spomenuti poziv, Android
operativni sistem će tražiti REST servis na uređaju na kojem se Android aplikacija i izvršava, tako
da je u URL adresi do servisa potrebno koristiti IP adresu računara ili domensku adresu. U ovom
slučaju koristi se IP adresa lokalnog računara na kojem je podignut REST servis a i sam emulator
Android aplikacije. Spomenutu adresu je potrebno promeniti da vodi do računara na kojem se
nalazi REST servis.
package rs.tfzr.rs.tfzr.data;
public class MTIPShared {
private static String _serviceBaseURL =
"http://192.168.1.150/mtip/services/";
public static String get_serviceBaseURL() {
return _serviceBaseURL;
}
public static void set_serviceBaseURL(String _serviceBaseURL) {
MTIPShared._serviceBaseURL = _serviceBaseURL;
}
}
Listing broj 2. Sadržaj klase MTIPShared
Naredni korak odnosi se na formiranje paketa rs.tfzr.utility i klasa HTTPPostCaller i
JSONReader. Klasa JSONReader poseduje statičke metode koje čitaju JSON string koji REST
servis pošalje dok klasa HTTPPostCaller poseduje statičke metode koje putem POST metode
šalju HTTP zahtev sa podacima ka bilo kojem HTTP serveru. U ovom slučaju spomenuta klasa
biće korišćena da se pošalju podatci REST servisu putem POST metode. U listingu koda broj 3 je
prikazan sadržaj klase JSONReader, dok se u listingu koda broj 4 nalazi sadržaj klase
HTTPPostCaller.
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
4
package rs.tfzr.utility;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class JSONReader {
public static String getJSONfromURL(String urlInput){
InputStream inputStream = null;
String result = "";
try {
URL url = new URL(urlInput);
HttpURLConnection urlConnection = (HttpURLConnection)
url.openConnection();
urlConnection.connect();
InputStream stream = urlConnection.getInputStream();
if (stream!=null) result = convertInputStreamToString(stream);
} catch (Exception e) {
result = e.toString();
}
return result;
}
private static String convertInputStreamToString(InputStream inputStream)
{
BufferedReader bufferedReader = new BufferedReader( new
InputStreamReader(inputStream));
String line = "";
String result = "";
try
{
while((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
}
catch (Exception ex) {}
return result;
}
}
Listing broj 3. Sadržaj klase JSONReader
package rs.tfzr.utility;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
5
public class HTTPPostCaller {
public static String performPostCall(String requestURL,
HashMap<String, String> postDataParams) {
URL url;
String response = "";
try
{
url = new URL(requestURL);
HttpURLConnection connection = (HttpURLConnection)
url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
OutputStream outputStream = connection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new
OutputStreamWriter(outputStream, "UTF-8"));
bufferedWriter.write(getPostDataString(postDataParams));
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
int responseCode=connection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK)
{
String line;
BufferedReader br=new BufferedReader(new
InputStreamReader(connection.getInputStream()));
while ((line=br.readLine()) != null) {
response+=line;
}
}
else response="";
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
public static String getPostDataString(HashMap<String, String> params) throws
UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.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"));
}
return result.toString();
}
}
Listing broj 4. Sadržaj klase HTTPPostCaller
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
6
DODAVANJE FUNKCIONALNOSTI FRAGMENTIMA I KLASE
MTIPSTUDENT I MTIPSTUDIJSKIPROGRAM
U listingu koda broj 5 prikazan je sadržaj klase MTIPStudijskiProgram, dok je u listingu koda
broj 6 prikazan sadržaj klase MTIPStudent. Objekat klase MTIPStudent sadrži objekat klase
MTIPStudijskiProgram pošto svaki student pripada nekom studijskom programu tj. smeru.
Spomenute klase sadrže anotacije serijalizacije polja koje vode poreklo iz prethodno dodate
GSON biblioteke. Vrednosti navedenih anotacija su nazivi polja iz JSON stringa koje treba dodeliti
odgovarajućim atributima klase. Spomenute anotacije se trebaju navoditi samo ako se naziv
atributa unutar klase razlikuje od naziva polja unutar JSON fajla. Ako se spomenuti nazvi slažu,
anotacije nema potrebe stavljati. Iako se u ovom slučaju nazivi atributa klasa i polja unutar JSON
fajla slažu, anotacije su postavljene primera radi. Takođe ukoliko se promeni naziv polja unutar
JSON fajla (stringa) promenom vrednosti unutar anotacije lako se ponovo uspostavlja veza.
Navedene anotacije se koriste sa deserijalizaciju JSON fajlova u Java objekte, i serijalizaciju Java
objekata u JSON fajlove (format). Navedene klase se nalaze unutar paketa rs.tfzr.classes.
package rs.tfzr.classes;
import com.google.gson.annotations.SerializedName;
public class MTIPStudijskiProgram {
@SerializedName("_idSmer")
protected int _idSmer;
@SerializedName("_nazivSmera")
protected String _nazivSmera;
@SerializedName("_sifra")
protected String _sifra;
public int get_idSmer() {
return _idSmer;
}
public void set_idSmer(int _idSmer) {
this._idSmer = _idSmer;
}
public String get_nazivSmera() {
return _nazivSmera;
}
public void set_nazivSmera(String _nazivSmera) {
this._nazivSmera = _nazivSmera;
}
public String get_sifra() {
return _sifra;
}
public void set_sifra(String _sifra) {
this._sifra = _sifra;
}
public MTIPStudijskiProgram()
{
this._idSmer = 0;
this._nazivSmera = "";
this._sifra = "";
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
7
}
@Override
public String toString() {
return this._nazivSmera;
}
}
Listing broj 5. Sadržaj klase MTIPStudijskiProgram
Klasa MTIPStudijskiProgram poseduje konstruktor i preklopljenu metodu toString koja se
koristi prilikom popunjavanja combobox-a (Spinner-a) koji se nalazi na formama (fragmentima)
za dodavanje i izmenu studenta.
package rs.tfzr.classes;
import com.google.gson.annotations.SerializedName;
public class MTIPStudent {
@SerializedName("_idStudent")
private int _idStudent;
@SerializedName("_ime")
private String _ime;
@SerializedName("_prezime")
private String _prezime;
@SerializedName("_index")
private String _index;
@SerializedName("_smer")
private MTIPStudijskiProgram _smer;
public int get_idStudent() {
return _idStudent;
}
public void set_idStudent(int _idStudent) {
this._idStudent = _idStudent;
}
public String get_ime() {
return _ime;
}
public void set_ime(String _ime) {
this._ime = _ime;
}
public String get_prezime() {
return _prezime;
}
public void set_prezime(String _prezime) {
this._prezime = _prezime;
}
public String get_index() {
return _index;
}
public void set_index(String _index) {
this._index = _index;
}
public MTIPStudijskiProgram get_smer() {
return _smer;
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
8
public void set_smer(MTIPStudijskiProgram _smer) {
this._smer = _smer;
}
public MTIPStudent()
{
this._idStudent = 0;
this._ime = "";
this._prezime = "";
this._index = "";
this._smer = new MTIPStudijskiProgram();
}
}
Listing broj 6. Sadržaj klase MTIPStudent
Funkcionalnost fragmentata (stranica) iz prethodne vežbe (MTIPLab05) će biti proširena i fokus
će biti na klasama PretragaFragment, StudentiFragment, StudentiDodavanjeFragment i
StudentiIzmenaFragment.
U listingu koda broj 7 prikazan je sadržaj klase PretragaFragment. Unutar spomenutog
fragmenta uspotavljena je veza sa EditText kontrolom i definisana je lista studenata koja će se
popuniti nakon poziva odgovarajuće metode REST servisa koji je formiran u vežbama MTIPLab01
i MTIPLab02. Takođe definisana je metoda PronadjiStudente koja prima jedan parametar tipa
String koji se odnosi na celo ili deo prezimena studenta kojeg treba pronaći. Ukoliko je vrednost
navedenog parametra prazan string metoda će prikazati sve studente koje se nalaze u bazi
podataka, u suprotnom, prikazuje studente čije prezime se parcijalno ili u potpunosti slaže sa
unetom vrednošću. Spomenuta metoda putem Handlera postuje odgovarajući zadatak (Task)
koji treba da se izvrši u pozadini (Runnable). U arhitekturi Android aplikacije (u višim verzijama)
nije dozvoljeno da se komunikacija sa HTTP servisima i ostala procesiranja izvršavaju u okviru
niti (thread-a) koja opslužuje korisnički interfejs. Unutar MTIP Studenti android aplikacije
spomenuta komunikacija se izvršava kao pozadinski proses i pri tome se upotrebom
ProgressDialog-a korisniku oduzima kontrola nad aplikacijom uz obaveštavanje korisnika o
izvršavanju pozadinskog procesa. Kad se pozadinski proces izvrši, spomenuti dijalog se uklanja, i
korisniku se dalje predaje kontrola nad aplikacijom. Pozadinski proces koji će prikupiti podatke
o studentima tako što će pozvati spomenuti REST servsis, preuzeti odgovor od istog, i poslati ga
GSON builderu koji će od navedenog napraviti objekte tipa MTIPStudenti oformljen je u formi
klase HTTPPretragaStudenataJSON koja nasleđuje klasu AsyncTask<String, Void, String> i
implementira metode doInBackground i onPostExecute. Unutar metode doInBackground se
poziva REST servis na osnovu parametara koje se prosleđuju objektu spomenute klase.
Spomenutom objektu se putem execute metode prosleđuje niz parametara. U ovom slučaju, to su
dva parametra: naziv metode REST servisa koji se poziva, i vrednost parametra koji se prosleđuje
spomenutom servisu. Pošto se radi o pretrazi studenata, vrednost prvog parametra je
“studentipregraga/?search=” i prezimeStudenta koje se preuzima iz EditText kontrole koja je
namenjena za pretragu. Unutar metode onPostExecute (koja se izvršava nakon metode
doInBackground) uklanjaju se svi rezultati pretrage iz LinearLayout-a _linearLayoutResults i
popunjavaju se rezultatima pretrage koji se nalaze unutar liste _studenti tako što se formira View
(pogled) na osnovu rasporeda komponenti layout_studenti_universal.xml, pristupa se layoutu
koji sadrži tastere za izmenu i brisanje radi uklanjanja istih (linearLayoutTasteri), formiraju se
veze ka labelama koje trebaju da prikažu odgovarajuće podatke o studentu, i unutar for petlje,
ciklično, pogled se formira, popuni podacima, i dodaje rasporedu linearLayoutResults koji ih
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
9
prikazuje redosledno, jedan ispod drugog. Na slici broj 5 prikazan je aktivan ProgressDialog
pretrage studenata, dok je na slici broj 6 prikazan je izgled fragmenta Pretraga sa rezultatima
pretrage.
package rs.tfzr.mtipstudenti;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import rs.tfzr.classes.MTIPStudent;
import rs.tfzr.rs.tfzr.data.MTIPShared;
import rs.tfzr.utility.JSONReader;
public class PretragaFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
protected TextView _textViewDodajNovogStudenta;
protected ImageView _imageViewPretraga;
protected Context _context;
protected ProgressDialog _progressDialog = null;
protected Runnable _studentiTask;
protected Handler _studentiHandler;
protected EditText _textPretraga;
protected LinearLayout _topLevelContainer;
protected LinearLayout _linearLayoutResults;
protected ArrayList<MTIPStudent> _studenti;
public PretragaFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static PretragaFragment newInstance(String param1, String param2) {
PretragaFragment fragment = new PretragaFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
10
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_pretraga, container,
false);
this._studenti = new ArrayList<MTIPStudent>();
this._context = rootView.getContext();
this._topLevelContainer =
(LinearLayout)rootView.findViewById(R.id.mainContainerPrezime);
this._textViewDodajNovogStudenta =
(TextView)rootView.findViewById(R.id.textViewDodajNovogStudenta);
this._topLevelContainer.removeView(this._textViewDodajNovogStudenta);
this._textPretraga =
(EditText)rootView.findViewById(R.id.editTextPrezimePretraga);
this._imageViewPretraga =
(ImageView)rootView.findViewById(R.id.imageViewPretraga);
this._imageViewPretraga.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String prezimePretraga = _textPretraga.getText().toString();
PronadjiStudente(prezimePretraga);
}
});
this._linearLayoutResults =
(LinearLayout)rootView.findViewById(R.id.layoutRezultatiPretrage);
return rootView;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
11
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
protected void PronadjiStudente(final String prezimeStudenta)
{
this._studentiHandler = new Handler();
this._studentiTask = new Runnable() {
@Override
public void run() {
HTTPPretragaStudenataJSON pretragaREQ = new
HTTPPretragaStudenataJSON();
String[] params = new String[2];
params[0] = "studentipretraga/?search=";
params[1] = prezimeStudenta;
pretragaREQ.execute(params);
}
};
this._studentiHandler.post(this._studentiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Preuzimam podatke ...", true);
}
protected class HTTPPretragaStudenataJSON extends AsyncTask<String, Void,
String> {
@Override
protected String doInBackground(String... strings) {
String serviceURL =
MTIPShared.get_serviceBaseURL()+strings[0]+strings[1];
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
_studenti.clear();
_studenti.addAll(Arrays.asList(gson.fromJson(
JSONReader.getJSONfromURL(serviceURL),
MTIPStudent[].class)));
return null;
}
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
_linearLayoutResults.removeAllViews();
LayoutInflater inflater = (LayoutInflater)
_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (MTIPStudent stud : _studenti)
{
View view = inflater.inflate(R.layout.layout_studenti_uiversal,
null);
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
12
LinearLayout layoutUniversal =
(LinearLayout)view.findViewById(R.id.linearLayoutStudentiUniversalContainer);
LinearLayout layoutTasteri =
(LinearLayout)view.findViewById(R.id.linearLayoutTasteri);
layoutUniversal.removeView(layoutTasteri);
TextView textViewPrezime =
(TextView)view.findViewById(R.id.textViewPrezimeDATA);
TextView textViewIme =
(TextView)view.findViewById(R.id.textViewImeDATA);
TextView textViewBrojIndeksa =
(TextView)view.findViewById(R.id.textViewBrojIndeksaDATA);
TextView textViewStudijskiProgram =
(TextView)view.findViewById(R.id.textViewStudijskiProgramDATA);
textViewPrezime.setText(stud.get_prezime());
textViewIme.setText(stud.get_ime());
textViewBrojIndeksa.setText(stud.get_index());
textViewStudijskiProgram.setText(stud.get_smer().get_nazivSmera());
_linearLayoutResults.addView(view);
}
}
}
}
Listing broj 7. Sadržaj klase PretragaFragment
Slika broj 5. Aktivna pretraga Slika broj 6. Rezultati pretrage
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
13
U listingu koda broj 8 prikazan je sadržaj klase StudentiFragment dok je na slici broj 7 prikazan
izgled navedenog fragmenta. Sadržaj spomenute klase gotovo je identičan sadržaju klase
PretragaFragmet i sa aspekta funkcionalnosti predstavlja proširenje spomenutog fragmenta.
Ključna razlika je u tome što se prilikom formiranja rezultata pretrage ne uklanja pogled (view)
koji sadrži tastere za izmenu (btnIzmeniStudenta) i brisanje (btnObrisiStudenda) studenta pa
se njima dodaju odgovarajući onClickListener-i kako bi se realizovala predviđena
funkcionalnost spomenutih tastera. Klikom na taster Izmena poziva se fragment
StudentiIzmenaFragment i istom se prosleđuje identifikator studenta koji treba da se izmeni.
Identifikator se čita na osnovu pozicije rezultata u listi rezultata (_linearLayoutResults) koji
odgovara poziciji objekta koji predstavlja odabranog studenta u listi studenata (_studenti).
Klikom na taster btnObrisiStudenta prikazuje se dijalog koji je prikazan na slici broj 8. Navedeni
dijalog pita korisnika da li želi da obriše odabranog studenta ili ne. Ukoliko je odgovor potvrdan
analogno klasi HTTPPretragaStudenataJSON formira se instanca klase
HTTPObrisiStudentaPost i putem execute metode prosleđuje se URL servisa koji treba da
realizuje brisanje studenta čiji se identifikator prosleđuje u listi parametara. Navedeno se
realizuje u doInBackground metodu spomenutog objekta. U onPostExecute metodi
spomenutog objekta se, ukoliko se spomenuti student uspešno obriše u bazi podataka, obrisani
student izbacuje iz liste objekata unutar Android aplikacije i osvežavaju se rezultati pretrage
uklanjanjem odgovarajućeg pogleda (view-a). Takođe deo koda koji se nalazio u klasi
HTTPPretragaStudenataJSON u onPostExecute metodi premešten je u metodu
PopulateResults.
package rs.tfzr.mtipstudenti;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import rs.tfzr.classes.MTIPStudent;
import rs.tfzr.rs.tfzr.data.MTIPShared;
import rs.tfzr.utility.HTTPPostCaller;
import rs.tfzr.utility.JSONReader;
public class StudentiFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
14
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
protected TextView _textViewDodajNovogStudenta;
protected ImageView _imageViewPretraga;
protected Context _context;
protected ProgressDialog _progressDialog = null;
protected Runnable _studentiTask;
protected Handler _studentiHandler;
protected EditText _textPretraga;
protected LinearLayout _topLevelContainer;
protected LinearLayout _linearLayoutResults;
protected ArrayList<MTIPStudent> _studenti;
public StudentiFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static StudentiFragment newInstance(String param1, String param2) {
StudentiFragment fragment = new StudentiFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_pretraga, container,
false);
this._studenti = new ArrayList<MTIPStudent>();
this._context = rootView.getContext();
this._topLevelContainer =
(LinearLayout)rootView.findViewById(R.id.mainContainerPrezime);
this._textPretraga =
(EditText)rootView.findViewById(R.id.editTextPrezimePretraga);
this._textViewDodajNovogStudenta =
(TextView)rootView.findViewById(R.id.textViewDodajNovogStudenta);
this._textViewDodajNovogStudenta.setOnClickListener(new
View.OnClickListener() {
@Override
public void onClick(View view) {
MTIPStudentiMain.displayView(new
StudentiDodavanjeFragment(),MTIPStudentiMain._activity);
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
15
}
});
this._imageViewPretraga =
(ImageView)rootView.findViewById(R.id.imageViewPretraga);
this._imageViewPretraga.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String prezimePretraga = _textPretraga.getText().toString();
PronadjiStudente(prezimePretraga);
}
});
this._linearLayoutResults =
(LinearLayout)rootView.findViewById(R.id.layoutRezultatiPretrage);
return rootView;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
protected void PronadjiStudente(final String prezimeStudenta)
{
this._studentiHandler = new Handler();
this._studentiTask = new Runnable() {
@Override
public void run() {
HTTPPretragaStudenataJSON pretragaREQ = new
HTTPPretragaStudenataJSON();
String[] params = new String[2];
params[0] = "studentipretraga/?search=";
params[1] = prezimeStudenta;
pretragaREQ.execute(params);
}
};
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
16
this._studentiHandler.post(this._studentiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Preuzimam podatke ...", true);
}
protected void ObrisiStudenta(final int idStudenta)
{
this._studentiHandler = new Handler();
this._studentiTask = new Runnable() {
@Override
public void run() {
HTTPObrisiStudentaPOST pretragaREQ = new
HTTPObrisiStudentaPOST();
String[] params = new String[2];
params[0] = "obrisistudenta";
params[1] = String.valueOf(idStudenta);
pretragaREQ.execute(params);
}
};
this._studentiHandler.post(this._studentiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Izvršavam zahtev ...", true);
}
protected void PopulateResults()
{
_linearLayoutResults.removeAllViews();
LayoutInflater inflater = (LayoutInflater)
_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (MTIPStudent stud : _studenti)
{
View view = inflater.inflate(R.layout.layout_studenti_uiversal,
null);
TextView textViewPrezime =
(TextView)view.findViewById(R.id.textViewPrezimeDATA);
TextView textViewIme =
(TextView)view.findViewById(R.id.textViewImeDATA);
TextView textViewBrojIndeksa =
(TextView)view.findViewById(R.id.textViewBrojIndeksaDATA);
TextView textViewStudijskiProgram =
(TextView)view.findViewById(R.id.textViewStudijskiProgramDATA);
final Button btnIzmeniStudenta =
(Button)view.findViewById(R.id.buttonIzmeniStudenta);
btnIzmeniStudenta.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
View removeView = (View)
btnIzmeniStudenta.getParent().getParent();
int itemIndex =
_linearLayoutResults.indexOfChild(removeView);
int idStudenta = _studenti.get(itemIndex).get_idStudent();
MTIPStudentiMain.displayView(StudentiIzmenaFragment.newInstance(idStudenta),MTIPS
tudentiMain._activity);
}
});
final Button btnObrisiStudenta =
(Button)view.findViewById(R.id.buttonObrisiStudenta);
btnObrisiStudenta.setOnClickListener(new View.OnClickListener() {
@Override
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
17
public void onClick(View view) {
new AlertDialog.Builder(_context)
.setTitle("MTIP Studenti")
.setMessage("Da li želite da obrišete studenta?")
.setPositiveButton("Da", new
DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int
which) {
// continue with delete
View removeView = (View)
btnObrisiStudenta.getParent().getParent();
int itemIndex =
_linearLayoutResults.indexOfChild(removeView);
MTIPStudent studentToDelete =
_studenti.get(itemIndex);
ObrisiStudenta(studentToDelete.get_idStudent());
}
})
.setNegativeButton("Ne", new
DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface
dialogInterface, int i) {
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
});
textViewPrezime.setText(stud.get_prezime());
textViewIme.setText(stud.get_ime());
textViewBrojIndeksa.setText(stud.get_index());
textViewStudijskiProgram.setText(stud.get_smer().get_nazivSmera());
_linearLayoutResults.addView(view);
}
}
protected class HTTPPretragaStudenataJSON extends AsyncTask<String, Void,
String> {
@Override
protected String doInBackground(String... strings) {
String serviceURL =
MTIPShared.get_serviceBaseURL()+strings[0]+strings[1];
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
_studenti.clear();
_studenti.addAll(Arrays.asList(gson.fromJson(
JSONReader.getJSONfromURL(serviceURL),
MTIPStudent[].class)));
return null;
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
18
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
PopulateResults();
}
}
protected class HTTPObrisiStudentaPOST extends AsyncTask<String, Void,
String>{
protected boolean _executed = false;
protected int _idStudenta = 0;
@Override
protected String doInBackground(String... strings) {
String serviceURL = MTIPShared.get_serviceBaseURL()+strings[0];
HashMap<String, String> postDataParams = new HashMap<>();
postDataParams.put("id",strings[1]);
this._idStudenta = Integer.parseInt(strings[1]);
this._executed =
Boolean.parseBoolean(HTTPPostCaller.performPostCall(serviceURL,postDataParams));
return null;
}
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
if(this._executed)
{
int studentListIndex = 0;
boolean found = false;
for(MTIPStudent stud : _studenti)
{
if (stud.get_idStudent() == this._idStudenta) {found = true;
break;}
studentListIndex++;
}
if (found)
{
_studenti.remove(studentListIndex);
_linearLayoutResults.removeViewAt(studentListIndex);
}
}
}
}
}
Listing broj 8. Sadržaj klase StudentiFragment
U listingu koda broj 9 prikazan je sadržaj klase StudentiDodavanjeFragment dok je na slici broj
9 prikazan izgled navedenog fragmenta. Sadržaj spomenute klase je krajnje specifičan u odnosu
na prethodno izložene listinge koda pošto se u onCreate metodu prvo uspostavljaju veze sa
komponentama koje se nalaze unutar rasporeda fragment_studenti_dodavanje_izmena.xml i
zatim se poziva metoda PreuzimiStudijskePrograme čija je uloga da formira objekat tipa
HTTPProcitajStudijskeProgrameJSON koji predstavlja pozadinski proces (izvedena je iz klase
AsyncTask) i analogno klasi HTTPPretragaStudenataJSON iz klasa (fragmenata)
PretragaFragment i StudentiFragment pozove REST servis i formira listu postojećih studijskih
programa (_studijskiProgrami). Spomeniti pozadinski proces pokreće se pozivom execute
metode uz prosleđivanje odgovarajućih parametara. Ukoliko je poziv spomenutog servisa
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
19
uspešan i lista studijskih programa (smerova) se oformi (navedeno se odvija u doInBackground
metodi) onda se spomenuta lista na osnovu preklopljene toString metode klase
MTIPStudijskiProgram putem ArrayAdapter-a povezujue sa Spinner kontrolom i unutar istog
se prikazuju trenutno dostupni smerovi (navedeno se odvija u onPostExecute metodi). Klikom
na taster btnPotvrdi poziva se metoda DodajStudenta čija je uloga da preuzme vrednosti iz
EditText i Spinner kontrola i zatim prosledi iste instanci klase HTTPDodajStudentaPOST koja
će iste proslediti odgovarajućem metodu REST servisa kako bi se dodao novi student u bazu
podataka. Navedeno se podrazumevano odvija u formi pozadinskog procesa (AsyncTask) uz
prikazivanje odgovarajućeg ProgressDialog-a. Ukoliko se student uspešno doda u bazu podataka
tj. poziv REST servisa je uspešan, korisnik se preusmerava na fragment StudentiFragment.
Klikom na taster btnOdustani korisnik se takođe preusmerava na fragment StudentiFragment.
Slika broj 7. Izgled fratmenta Studenti Slika broj 8. Dijalog brisanja studena
package rs.tfzr.mtipstudenti;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
20
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import rs.tfzr.classes.MTIPStudent;
import rs.tfzr.classes.MTIPStudijskiProgram;
import rs.tfzr.rs.tfzr.data.MTIPShared;
import rs.tfzr.utility.HTTPPostCaller;
import rs.tfzr.utility.JSONReader;
public class StudentiDodavanjeFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
protected TextView _textViewDodavanjeLabela;
protected Context _context;
protected Button _btnPotvrdi;
protected Button _btnOdustani;
protected LinearLayout _linearLayoutIDStudenta;
protected LinearLayout _linearLauyoutMain;
protected ArrayList<MTIPStudijskiProgram> _studijskiProgrami;
protected Spinner _spinnerStudijskiProgram;
protected ProgressDialog _progressDialog = null;
protected Runnable _studijskiProgramiTask;
protected Handler _studijskiProgramiHandler;
protected MTIPStudijskiProgram _odabraniStudijskiProgram;
protected EditText _editTextPrezimeStudenta;
protected EditText _editTextimeStudenta;
protected EditText _editTextBrojIndeksa;
public StudentiDodavanjeFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static StudentiDodavanjeFragment newInstance(String param1, String
param2) {
StudentiDodavanjeFragment fragment = new StudentiDodavanjeFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
21
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView =
inflater.inflate(R.layout.fragment_studenti_dodavanje_izmena, container, false);
this._context = rootView.getContext();
this._textViewDodavanjeLabela =
(TextView)rootView.findViewById(R.id.textViewStudentiNazivAkcije);
this._textViewDodavanjeLabela.setText("Dodavanje studenta");
this._linearLauyoutMain =
(LinearLayout)rootView.findViewById(R.id.dodavanjeIzmenaMainLinearLayout);
this._linearLayoutIDStudenta =
(LinearLayout)rootView.findViewById(R.id.linearLayoutIDStudenta);
this._linearLauyoutMain.removeView(this._linearLayoutIDStudenta);
this._btnPotvrdi = (Button)rootView.findViewById(R.id.buttonPotvrdi);
this._btnOdustani = (Button)rootView.findViewById(R.id.buttonOdustani);
this._btnPotvrdi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DodajStudenta();
}
});
this._btnOdustani.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MTIPStudentiMain.displayView(new
StudentiFragment(),MTIPStudentiMain._activity);
}
});
this._editTextPrezimeStudenta =
(EditText)rootView.findViewById(R.id.editTextPrezimeDATA);
this._editTextimeStudenta =
(EditText)rootView.findViewById(R.id.editTextImeDATA);
this._editTextBrojIndeksa =
(EditText)rootView.findViewById(R.id.editTextIndeksDATA);
this._studijskiProgrami = new ArrayList<MTIPStudijskiProgram>();
this._spinnerStudijskiProgram =
(Spinner)rootView.findViewById(R.id.spinnerStudijskiProgrami);
this.PreuzmiStudijskePrograme();
return rootView;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
22
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
protected void PreuzmiStudijskePrograme()
{
this._studijskiProgramiHandler = new Handler();
this._studijskiProgramiTask = new Runnable() {
@Override
public void run() {
HTTPProcitajStudijskeProgrameJSON smeroviREQ = new
HTTPProcitajStudijskeProgrameJSON();
String[] params = new String[1];
params[0] = "smerovi";
smeroviREQ.execute(params);
}
};
this._studijskiProgramiHandler.post(this._studijskiProgramiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Preuzimam podatke ...", true);
}
protected class HTTPProcitajStudijskeProgrameJSON extends AsyncTask<String,
Void, String> {
@Override
protected String doInBackground(String... strings) {
String serviceURL = MTIPShared.get_serviceBaseURL()+strings[0];
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
_studijskiProgrami.clear();
_studijskiProgrami.addAll(Arrays.asList(gson.fromJson(
JSONReader.getJSONfromURL(serviceURL),
MTIPStudijskiProgram[].class)));
return null;
}
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
ArrayAdapter<MTIPStudijskiProgram> adapter =
new ArrayAdapter<MTIPStudijskiProgram>(_context,
android.R.layout.simple_spinner_dropdown_item, _studijskiProgrami);
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
23
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
_spinnerStudijskiProgram.setAdapter(adapter);
if (_studijskiProgrami.size()>0) _odabraniStudijskiProgram =
_studijskiProgrami.get(0);
else _odabraniStudijskiProgram = new MTIPStudijskiProgram();
}
}
protected void DodajStudenta()
{
final String prezime =
this._editTextPrezimeStudenta.getText().toString();
final String ime = this._editTextimeStudenta.getText().toString();
final String brojIndeksa =
this._editTextBrojIndeksa.getText().toString();
final int idSmera =
_studijskiProgrami.get(_spinnerStudijskiProgram.getSelectedItemPosition()).get_id
Smer();
this._studijskiProgramiHandler = new Handler();
this._studijskiProgramiTask = new Runnable() {
@Override
public void run() {
HTTPDodajStudentaPOST dodajStudentaREQ = new
HTTPDodajStudentaPOST();
String[] params = new String[5];
params[0] = "dodajstudenta";
params[1] = prezime;
params[2] = ime;
params[3] = brojIndeksa;
params[4] = String.valueOf(idSmera);
dodajStudentaREQ.execute(params);
}
};
this._studijskiProgramiHandler.post(this._studijskiProgramiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Izvršavam zahtev ...", true);
}
protected class HTTPDodajStudentaPOST extends AsyncTask<String, Void,
String>{
protected boolean _executed = false;
@Override
protected String doInBackground(String... strings) {
String serviceURL = MTIPShared.get_serviceBaseURL()+strings[0];
HashMap<String, String> postDataParams = new HashMap<>();
postDataParams.put("Prezime",strings[1]);
postDataParams.put("Ime",strings[2]);
postDataParams.put("Indeks",strings[3]);
postDataParams.put("idSmer",strings[4]);
this._executed =
Boolean.parseBoolean(HTTPPostCaller.performPostCall(serviceURL,postDataParams));
return null;
}
@Override
protected void onPostExecute(String result) {
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
24
_progressDialog.dismiss();
if(this._executed) MTIPStudentiMain.displayView(new
StudentiFragment(),MTIPStudentiMain._activity);
}
}
}
Listing broj 9. Sadržaj klase StudentiDodavanjeFragment
Slika broj 9. Izgled fratmenta
StudentiDodavanjeFragment
Slika broj 10. Izgled fratmenta
StudentiIzmenaFragment
U listingu koda broj 10 prikazan je sadržaj klase StudentiIzmenaFragment dok je na slici broj
10 prikazan izgled navedenog fragmenta. Sadržaj spomenute klase je veoma sličan sadržaju klase
(fragmenta) StudentiDodavanjeFragment uz par krucijalnih razlika. Prvo, instanca klase
StudentiIzmenaFragment se formira pozivom statičke metode newInstance i pri tome se
preuzima parametar idStudenta. Na osnovu prosleđenog parametra, pozivom metode
PreuzmiPodatkeOStudentuISmerovima (koja kao parametar prima identifikator studenta)
formira se instanca klase HTTPProcitajPodatkeOStudentuISmerovimaJSON koja je izvedena
iz klase AsyncTask i u doInBacground metodu formira listu dostupnih studijskih programa
(kako bi se popunila Spinner kontrola) a zatim preuzima i informacije o studentu koji treba da se
izmeni. Navedene informacije preuzimaju se pozivom metoda REST servisa. U onPostExecute
metodu spomenute klase lista dostupnih studijskih programa se povezuje putem ArrayAdapter-
a sa odgovarajućom Spinner kontrolom i zatim se na osnovu informacija o traženom studentu
popunjava sadržaj EditText kontrola i (unutar spomenute Spinner kontrole) prikazuje se
studijski program trenutno odabranog studenta iz spomenute liste dostupnih studijskih
programa. Klikom na taster btnPotvrdi poziva se metoda IzmeniStudenta čija je uloga da
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
25
preuzme vrednosti iz EditText i Spinner kontrola i zatim prosledi iste instanci klase
HTTPIzmeniStudentaPOST koja će iste proslediti odgovarajućem metodu REST servisa kako bi
se izmenio postojeći (odabrani) student. Navedeno se podrazumevano odvija u formi
pozadinskog procesa (AsyncTask) uz prikazivanje odgovarajućeg ProgressDialog-a. Ukoliko se
informacije odabranog studenta uspešno izmene tj. poziv REST servisa je uspešan, korisnik se
preusmerava na fragment StudentiFragment. Klikom na taster btnOdustani korisnik se takođe
preusmerava na fragment StudentiFragment.
package rs.tfzr.mtipstudenti;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import rs.tfzr.classes.MTIPStudent;
import rs.tfzr.classes.MTIPStudijskiProgram;
import rs.tfzr.rs.tfzr.data.MTIPShared;
import rs.tfzr.utility.HTTPPostCaller;
import rs.tfzr.utility.JSONReader;
public class StudentiIzmenaFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String _idStudentaNaziv = "idStudenta";
// TODO: Rename and change types of parameters
private int _idStudenta = 0;
private StudentiIzmenaFragment.OnFragmentInteractionListener mListener;
protected TextView _textViewDodavanjeLabela;
protected Context _context;
protected Button _btnPotvrdi;
protected Button _btnOdustani;
protected EditText _editTextIDStudenta;
protected EditText _editTextPrezimeStudenta;
protected EditText _editTextimeStudenta;
protected EditText _editTextBrojIndeksa;
protected Spinner _spinnerStudijskiProgram;
protected ArrayList<MTIPStudijskiProgram> _studijskiProgrami;
protected MTIPStudent _izabraniStudent;
protected ProgressDialog _progressDialog = null;
protected Runnable _studijskiProgramiTask;
protected Handler _studijskiProgramiHandler;
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
26
public StudentiIzmenaFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static StudentiIzmenaFragment newInstance(int idStudenta) {
StudentiIzmenaFragment fragment = new StudentiIzmenaFragment();
Bundle args = new Bundle();
args.putInt("idStudenta",idStudenta);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) this._idStudenta =
getArguments().getInt(_idStudentaNaziv);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView =
inflater.inflate(R.layout.fragment_studenti_dodavanje_izmena, container, false);
this._context = rootView.getContext();
this._textViewDodavanjeLabela =
(TextView)rootView.findViewById(R.id.textViewStudentiNazivAkcije);
this._textViewDodavanjeLabela.setText("Izmena studenta");
this._btnPotvrdi = (Button)rootView.findViewById(R.id.buttonPotvrdi);
this._btnPotvrdi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
IzmeniStudenta();
}
});
this._btnOdustani = (Button)rootView.findViewById(R.id.buttonOdustani);
this._btnOdustani.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MTIPStudentiMain.displayView(new
StudentiFragment(),MTIPStudentiMain._activity);
}
});
this._editTextIDStudenta =
(EditText)rootView.findViewById(R.id.editTextIDStudentaDATA);
this._editTextPrezimeStudenta =
(EditText)rootView.findViewById(R.id.editTextPrezimeDATA);
this._editTextimeStudenta =
(EditText)rootView.findViewById(R.id.editTextImeDATA);
this._editTextBrojIndeksa =
(EditText)rootView.findViewById(R.id.editTextIndeksDATA);
this._studijskiProgrami = new ArrayList<MTIPStudijskiProgram>();
this._spinnerStudijskiProgram =
(Spinner)rootView.findViewById(R.id.spinnerStudijskiProgrami);
this.PreuznmiPodatkeOStudentuISmerovima(this._idStudenta);
return rootView;
}
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
27
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof
StudentiDodavanjeFragment.OnFragmentInteractionListener) {
mListener = (StudentiIzmenaFragment.OnFragmentInteractionListener)
context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
protected void PreuznmiPodatkeOStudentuISmerovima(final int idStudenta)
{
this._studijskiProgramiHandler = new Handler();
this._studijskiProgramiTask = new Runnable() {
@Override
public void run() {
HTTPProcitaPodatkeOStudentuISmerovimaJSON studentISmeroviREQ =
new HTTPProcitaPodatkeOStudentuISmerovimaJSON();
String[] params = new String[3];
params[0] = "student/?idStudent=";
params[1] = "smerovi";
params[2] = String.valueOf(idStudenta);
studentISmeroviREQ.execute(params);
}
};
this._studijskiProgramiHandler.post(this._studijskiProgramiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Preuzimam podatke ...", true);
}
protected class HTTPProcitaPodatkeOStudentuISmerovimaJSON extends
AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... strings) {
String serviceURLStudent =
MTIPShared.get_serviceBaseURL()+strings[0]+strings[2];
String serviceURLSmerovi =
MTIPShared.get_serviceBaseURL()+strings[1];
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
28
// smerovi
_studijskiProgrami.clear();
_studijskiProgrami.addAll(Arrays.asList(gson.fromJson(
JSONReader.getJSONfromURL(serviceURLSmerovi),
MTIPStudijskiProgram[].class)));
// student
_izabraniStudent = new MTIPStudent();
_izabraniStudent = Arrays.asList(gson.fromJson(
JSONReader.getJSONfromURL(serviceURLStudent),
MTIPStudent[].class)).get(0);
return null;
}
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
ArrayAdapter<MTIPStudijskiProgram> adapter =
new ArrayAdapter<MTIPStudijskiProgram>(_context,
android.R.layout.simple_spinner_dropdown_item, _studijskiProgrami);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
_spinnerStudijskiProgram.setAdapter(adapter);
_editTextIDStudenta.setText(String.valueOf(_izabraniStudent.get_idStudent()));
_editTextPrezimeStudenta.setText(_izabraniStudent.get_prezime());
_editTextimeStudenta.setText(_izabraniStudent.get_ime());
_editTextBrojIndeksa.setText(_izabraniStudent.get_index());
int indexSmera = 0;
for(MTIPStudijskiProgram sp : _studijskiProgrami)
{
if (sp.get_idSmer()==_izabraniStudent.get_smer().get_idSmer())
{break;}
indexSmera++;
}
_spinnerStudijskiProgram.setSelection(indexSmera);
}
}
protected void IzmeniStudenta()
{
_izabraniStudent.set_prezime(_editTextPrezimeStudenta.getText().toString());
_izabraniStudent.set_ime(_editTextimeStudenta.getText().toString());
_izabraniStudent.set_index(_editTextBrojIndeksa.getText().toString());
_izabraniStudent.set_smer(_studijskiProgrami.get(_spinnerStudijskiProgram.getSele
ctedItemPosition()));
this._studijskiProgramiHandler = new Handler();
this._studijskiProgramiTask = new Runnable() {
@Override
public void run() {
HTTPIzmeniStudentaPOST izmeniStudentaPOST = new
HTTPIzmeniStudentaPOST();
String[] params = new String[6];
dr Predrag Pecev – Mobilne tehnologije i programiranje – Vežbe 2017 – 2018 – R2 -
Podložno izmeni - Nerecenzirani materijal
29
params[0] = "izmenistudenta";
params[1] = _izabraniStudent.get_prezime();
params[2] = _izabraniStudent.get_ime();
params[3] = _izabraniStudent.get_index();
params[4] =
String.valueOf(_izabraniStudent.get_smer().get_idSmer());
params[5] = String.valueOf(_izabraniStudent.get_idStudent());
izmeniStudentaPOST.execute(params);
}
};
this._studijskiProgramiHandler.post(this._studijskiProgramiTask);
this._progressDialog = ProgressDialog.show(this._context,
"Molimo Vas sačekajte ...", "Izvršavam zahtev ...", true);
}
protected class HTTPIzmeniStudentaPOST extends AsyncTask<String, Void,
String>{
protected boolean _executed = false;
@Override
protected String doInBackground(String... strings) {
String serviceURL = MTIPShared.get_serviceBaseURL()+strings[0];
HashMap<String, String> postDataParams = new HashMap<>();
postDataParams.put("Prezime",strings[1]);
postDataParams.put("Ime",strings[2]);
postDataParams.put("Indeks",strings[3]);
postDataParams.put("idSmer",strings[4]);
postDataParams.put("id",strings[5]);
this._executed =
Boolean.parseBoolean(HTTPPostCaller.performPostCall(serviceURL,postDataParams));
return null;
}
@Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
if(this._executed) MTIPStudentiMain.displayView(new
StudentiFragment(),MTIPStudentiMain._activity);
}
}
}
Listing broj 10. Sadržaj klase StudentiIzmenaFragment
NAPOMENA : Dizajn izložene aplikacije je krajnje jednostavan i nije optimizovan sa aspetka
detaljnog definisanja resursa za sve rezolucije, tačnog pozicioniranja labela i dr. pošto je cilj istih
da se pokaže osnovna koncepcija i funkcionalnost Android aplikacija i povezivanje istih sa REST
servisom. Namerni dizajnerski propusti će biti korigovani u narednoj verziji vežbi.