Sveiki.
Per UART gautus duomenis būtina perkelti į Veiklą. Tai galima padaryti sukūrus giją veikloje, kurioje būtų galima organizuoti trumpą (!isInterrupted()) kilpą ir nuskaityti duomenis iš UART buferio. Po to, iškvietus veiklos vartotojo sąsajos giją - MainActivity.this.runOnUiThread(new Runnable() ), atlikite reikiamus veiksmus su šia veikla. Bet jei iš pagrindinės veiklos iškviečiame kitas veiklas, tai organizuota gija neleidžia praeiti duomenis į naujai kuriamas Veiklas.Jei gerai suprantu, kad duomenys iš srauto būtų perkelti į bet kurią Veiklą, srautas turi būti sukurtas ne Veikloje, o Paslaugoje.
Klausimas: duomenys atkeliavo per UART, temoje (kuri sukurta Servce) reikia perkelti duomenis i Activity, kuri dabar yra aktyvi, kaip tai galima padaryti ir ar tai apskritai daroma?
1 atsakymas
Kiekvienoje veikloje sukurkite tvarkyklę. Šios veiklos metodu onResume() atliekamas bindService(). Ten vienas iš parametrų yra sąsaja ServiceConnection. Įdiekite ją bent ta pačia veikla. Įdiekite joje metodą onServiceConnected(). Šiame atgalinio skambučio metu pati paslauga yra vienas iš parametrų. Taigi vadinkite šią paslaugą savo setHandler() metodu. Perduokite ten tvarkyklę, kuri yra dabartinėje veikloje. Bet mesti gaunamus duomenis per UART į šios tvarkyklės paslaugą. Beje, Handler tradiciškai veikia pagrindinėje gijoje, todėl runOnUiThread vykdyti nereikės.
Paskutinis atnaujinimas: 2018-04-03
Intent objektas naudojamas duomenims perduoti tarp dviejų veiklų. Naudodami putExtra() metodą, galite pridėti raktą ir su juo susijusią reikšmę.
Pavyzdžiui, perkeliant iš dabartinės veiklos į SecondActivity eilutę „Hello World“ su raktu „hello“:
// sukurti ketinimą paleisti SecondActivity Intent intent = new Intent(this, SecondActivity.class); // objekto perdavimas su raktu "hello" ir reikšme "Hello World" intent. putExtra("hello", "Hello World"); // paleisti SecondActivity startActivity(intent);
Duomenims perduoti naudojamas putExtra() metodas, leidžiantis perkelti paprasčiausių tipų duomenis - String, int, float, double, long, short, byte, char, šių tipų masyvus arba serializable objektą. sąsaja kaip vertė.
Norėdami gauti pateiktus duomenis, kai įkeliama SecondActivity, galite naudoti metodą get(), kuris perduodamas objekto raktui:
Argumentų rinkinys = getIntent().getExtras(); Eilutės pavadinimas = argumentai.get("labas").toString(); // Labas pasauli
Priklausomai nuo siunčiamų duomenų tipo, gaudami objektą Bundle galime naudoti daugybę metodų. Visi jie naudoja objekto raktą kaip parametrą. Pagrindiniai iš jų yra:
get() : bendras metodas, grąžinantis objekto tipo reikšmę. Atitinkamai, gavimo laukas, ši reikšmė turi būti konvertuota į norimą tipą
getString() : grąžina String tipo objektą
getInt() : grąžina int reikšmę
getByte() : grąžina baito reikšmę
getChar() : grąžina char tipo reikšmę
getShort() : grąžina trumpo tipo reikšmę
getLong() : grąžina ilgą reikšmę
getFloat() : grąžina slankiąją reikšmę
getDouble() : grąžina dvigubą reikšmę
getBoolean() : grąžina loginę reikšmę
getCharArray() : grąžina char objektų masyvą
getIntArray() : grąžina int objektų masyvą
getFloatArray() : grąžina plūduriuojančių objektų masyvą
getSerializable() : grąžina Serializable sąsajos objektą
Mūsų projekte apibrėžkime dvi veiklas: „MainActivity“ ir „SecondActivity“.
„SecondActivity“ kode apibrėžkime duomenų gavimą:
Paketas com.example.eugene.serializeapp; importuoti android.support.v7.app.AppCompatActivity; importuoti android.os.Bundle; importuoti android.widget.TextView; viešoji klasė SecondActivity išplečia AppCompatActivity ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setTextSize(20); textView.setPadding(16, 16, 16, 16) ); Argumentų rinkinys = getIntent().getExtras(); if(argumentai!=null)( eilutės pavadinimas = argumentai.get("vardas").toString(); String company = argumentai.getString("įmonė"); int kaina = argumentai.getInt("kaina"); textView.setText("Pavadinimas: " + pavadinimas + "\nĮmonė: " + įmonė + "\nKaina: " + kaina); ) setContentView(textView); ) )
Tokiu atveju „SecondActivity“ mes gauname visus duomenis iš „Bundle“ objekto ir rodome juos „TextView“ teksto lauke. Daroma prielaida, kad šiai veiklai bus perduoti trys elementai – dvi eilutės su raktų pavadinimu ir įmonės pavadinimu bei skaičius su kainos raktu.
Dabar apibrėžkime duomenų perdavimą į SecondActivity. Pavyzdžiui, faile activity_main.xml apibrėžkime šią MainActivity sąsają:
Čia nustatyti trys teksto laukai duomenims įvesti ir mygtukas.
„MainActivity“ klasėje apibrėžkite šį turinį:
Paketas com.example.eugene.serializeapp; importuoti android.content.Intent; importuoti android.support.v7.app.AppCompatActivity; importuoti android.os.Bundle; importuoti android.view.View; importuoti android.widget.EditText; public class MainActivity išplečia AppCompatActivity ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ) public void onClick(View v) (galutinis EditText nameText = RView.By .name); final EditText companyText = findViewById(R.id.company); galutinė EditText kainaText = findViewById(R.id.price); eilutės pavadinimas = nameText.getText().toString(); String company = companyText.getText( ).toString(); int kaina = Integer.parseInt(kainaText.getText().toString()); Intent intent = new Intent(this, SecondActivity.class); intent.putExtra("pavadinimas", pavadinimas); ketinimas. putExtra("įmonė", įmonė); intent. putExtra("kaina", kaina); startActivity(intent); ) )
Mygtukų paspaudimo tvarkyklėje gauname duomenis, įvestus į EditText teksto laukus ir perduodame juos objektui Inten, naudodami putExtra() metodą. Tada pradedame SecondActivity.
Dėl to, paspaudus mygtuką, bus paleista SecondActivity, kuri gaus tam tikrus teksto laukuose įvestus duomenis.
Sudėtingų objektų perdavimas
Aukščiau pateiktame pavyzdyje buvo perduoti paprasti duomenys – skaičiai, eilutės. Tačiau galime perkelti ir sudėtingesnius duomenis. Šiuo atveju naudojamas serializacijos mechanizmas.
Pavyzdžiui, apibrėžkime produkto klasę mūsų projekte:
Paketas com.example.eugene.serializeapp; importuoti java.io.Serializable; viešoji klasė Produktas įgyvendina Serializable (privatus eilutės pavadinimas; privati eilutės įmonė; privati int kaina; vieša gaminys (eilutės pavadinimas, eilutės įmonė, int kaina)( this.name = pavadinimas; this.company = įmonė; this.price = kaina; ) public String getName() ( grąžinamas pavadinimas; ) public void setName(Eilutės pavadinimas) ( this.name = pavadinimas; ) public String getCompany() ( grąžinti įmonė; ) public void setCompany(String company) ( this.company = įmonė; ) public int getPrice() ( grąžinimo kaina; ) public void setPrice(int price) ( this.price = kaina; ) )
Atminkite, kad ši klasė įgyvendina Serializable sąsają. Dabar pakeiskime MainActivity kodą:
Paketas com.example.eugene.serializeapp; importuoti android.content.Intent; importuoti android.support.v7.app.AppCompatActivity; importuoti android.os.Bundle; importuoti android.view.View; importuoti android.widget.EditText; public class MainActivity išplečia AppCompatActivity ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ) public void onClick(View v) (galutinis EditText nameText = RView.By .name); final EditText companyText = findViewById(R.id.company); galutinė EditText kainaText = findViewById(R.id.price); eilutės pavadinimas = nameText.getText().toString(); String company = companyText.getText( ).toString();int kaina = Integer.parseInt(kainaText.getText().toString()); Produkto produktas = naujas produktas (pavadinimas, įmonė, kaina); Intent intent = naujas tikslas (tai, SecondActivity.class); intent.putExtra(Product.class.getSimpleName(), produktas; startActivity(intent); ) )
Dabar vietoj trijų skirtingų duomenų perduodamas vienas Produkto objektas. Raktas yra metodo Product.class.getSimpleName() rezultatas, kuris iš esmės grąžina klasės pavadinimą.
Ir pakeiskite SecondActivity klasę:
Paketas com.example.eugene.serializeapp; importuoti android.support.v7.app.AppCompatActivity; importuoti android.os.Bundle; importuoti android.widget.TextView; viešoji klasė SecondActivity išplečia AppCompatActivity ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setTextSize(20); textView.setPadding(16, 16, 16, 16) ); Argumentų rinkinys = getIntent().getExtras(); galutinis produkto produktas; if(arguments!=null)( product = (produktas) arguments.getSerializable(Product.class.getSimpleName()); textView.setText("Pavadinimas: " + product.getPavadinimas() + "\nĮmonė: " + produktas.getCompany() + "\nKaina: " + String.valueOf(product.getPrice())); ) setContentView(textView); ) )
Metodas getSerializable() naudojamas duomenims gauti, nes produktų klasė įgyvendina Serializable sąsają. Taigi, vietoj skirtingų duomenų rinkinio galime perduoti vieną objektą.
Programą ne visada sudaro vienas ekranas. Pavyzdžiui, mes sukūrėme labai naudingą programą ir vartotojas nori sužinoti, kas yra jos autorius. Jis paspaudžia mygtuką „Apie“ ir patenka į naują ekraną su naudinga informacija apie programos versiją, autorių, svetainės adresą, kiek autoriaus kačių ir kt. Veiklos ekraną įsivaizduokite kaip tinklalapį su nuoroda į kitą puslapį. Jei pažvelgsite į kodą faile MainActivity.java iš ankstesnių pamokų pamatysite, kad mūsų klasė Pagrindinis užsiėmimas taip pat taikoma Veikla(arba jo įpėdiniai) arba, tiksliau, paveldima iš jo.
Viešoji klasė „MainActivity“ išplečia „AppCompatActivity“.
Kaip galite spėti, turėtume sukurti naują klasę, kuri gali atrodyti Pagrindinis užsiėmimas ir tada kažkaip pereiti prie jo spustelėjus mygtuką.
Eksperimentui paimsime programą iš pirmos pamokos ir naudosime mygtuką eksperimentams (arba sukursime naują projektą vienu mygtuku ekrane). Tada sukurkime naują formą, kad būtų rodoma naudinga informacija. Pavyzdžiui, parodykime vartotojui, ką katė daro, kai eina į kairę ir į dešinę. Sutikite, tai labai svarbi informacija, kuri duoda raktą į visatos išnarpliojimą.
Naują veiklą kursime rankiniu būdu, nors studija turi jau paruoštus šablonus. Tačiau nėra nieko sudėtingo ir norint geriau suprasti, naudinga viską daryti rankomis.
Sukurkime naują XML žymėjimo failą activity_about.xml aplanke res/išdėstymas. Dešiniuoju pelės mygtuku spustelėkite aplanką išdėstymas ir kontekstiniame meniu pasirinkite Naujas | Maketo išteklių failas. Atsiras dialogo langas. Pirmame lauke įveskite failo pavadinimą veikla_apie. Antrame, turite įvesti šakninį elementą. Pagal numatytuosius nustatymus jis yra ConstraintLayout. Ištrinkite tekstą ir įveskite slinkties rodinys. Pakanka įvesti keletą simbolių, kad studija pasiūlytų paruoštas parinktis, galite iš karto paspausti Enter, nelaukdami, kol bus įvestas visas žodis:
Gauname atitinkamą ruošinį, į kurį įterpiame elementą teksto rodinys.
Informacija bus gaunama iš išteklių, būtent iš eilutės šaltinio apie_tekstą. Dabar jis paryškintas raudonai, o tai rodo informacijos nebuvimą. galima būtų paspausti Alt + Enter ir dialogo lange įveskite tekstą. Tačiau mūsų pavyzdyje šis metodas neveiks, nes mūsų tekstas bus kelių eilučių, naudojant valdymo simbolius. Taigi darykime kitaip. Atidarykime failą res/values/strings.xml ir rankiniu būdu įveskite šį tekstą:
Naudojome paprasčiausias HTML teksto formatavimo žymas, pvz , , . Mūsų pavyzdyje užtenka paryškinti žodžius, nurodančius katę ir judėjimo kryptį. Norėdami išversti tekstą į naują eilutę, naudokite simbolius \n. Pridėkime dar vieną naujojo ekrano pavadinimo eilutės šaltinį:
Suprantama su žymėjimu. Tada turite sukurti lango klasę AboutActivity.java. Pasirinkite iš meniu failas | Naujas | Java klasė ir užpildykite reikiamus laukus. Iš pradžių pakanka nurodyti tik pavadinimą. Tada užsiimk kitomis sritimis.
Pradėkime pasiruošimą.
Dabar klasė beveik tuščia. Pridėkite kodą rankiniu būdu. Klasė turi būti paveldima iš abstrakčios klasės Veikla ar jo artimieji FragmentActivity, AppCompatActivity ir tt Pridedant pratęsia veiklą. Veiklos klasė turi turėti metodą onCreate (). Užveskite pelės žymeklį klasės viduje ir pasirinkite meniu kodas | Nepaisyti metodų(Ctrl + O). Dialogo lange mes ieškome norimos klasės, galite įvesti pirmuosius klaviatūros simbolius greitai paieškai. Sukurtame metode turite iškviesti metodą setContentView(), kuri ekrane įkels paruoštą žymėjimą. Turėsime tokį variantą.
Paketas en.alexanderklimov.helloworld; importuoti android.app.Activity; importuoti android.os.Bundle; /** * Sukūrė Aleksandras Klimovas 2014-12-01. */ viešoji klasė „AboutActivity“ išplečia veiklą ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_about); ) )
Dabar prasideda svarbiausias dalykas. Mūsų užduotis yra pereiti į naują ekraną, kai pirmame ekrane paspaudžiamas mygtukas. Grįžkime į klasę Pagrindinis užsiėmimas. Parašykime mygtuko paspaudimo tvarkyklę:
Public void onClick(View view) ( Intent intent = new Intent(MainActivity.this, AboutActivity.class); startActivity(intent); )
Čia naudojau pamokoje aprašytą mygtukų paspaudimo valdymo būdą.
Norėdami pradėti naują ekraną, turite sukurti klasės egzempliorių Tikslas ir pirmame parametre nurodykite dabartinę klasę, o antrajame - perėjimo klasę, mes turime tai Apie veiklą. Po to metodas vadinamas startActivity(), kuris paleidžia naują ekraną.
Jei dabar bandysite išbandyti programą emuliatoriuje, gausite klaidos pranešimą. Ką mes padarėme ne taip? Praleidome vieną svarbų žingsnį. Reikia užregistruoti naują Veikla manifeste AndroidManifest.xml. Raskite šį failą savo projekte ir dukart spustelėkite jį. Atsidarys failo redagavimo langas. Pridėkite naują žymą
Čia praverčia eilučių ištekliai apie_pavadinimą. Paleiskite programą, spustelėkite mygtuką ir atidarykite langą Apie programą. Taigi, mes išmokome sukurti naują langą ir jį iškviesti spustelėjus mygtuką. Ir mūsų žinioje atsirado megapatogi programa – dabar visada bus po ranka užuomina, ką daro katė, eidama į kairę.
Dar kartą atkreipiu dėmesį į tai, kad antroji sukurta veiklos klasė turi būti paveldėta iš klasės Veikla ar panašiai ( Sąrašo veikla ir pan.), turėti XML žymėjimo failą (jei reikia) ir būti įrašytas manifeste.
Iškvietęs metodą startActivity() prasidės nauja veikla (šiuo atveju Apie veiklą), jis taps matomas ir persikels į krūvos, kurioje yra veikiantys komponentai, viršų. Iškviečiant metodą baigti() iš naujos veiklos (arba paspaudus aparatūros grįžimo klavišą) ji bus uždaryta ir pašalinta iš krūvos. Kūrėjas taip pat gali pereiti prie ankstesnės (ar bet kurios kitos) veiklos naudodamas tą patį metodą startActivity().
Trečiojo ekrano kūrimas – būdas tinginiams
Programuotojai, kaip ir katės, yra tingūs padarai. Visada atminkite, kad veiklai turite sukurti žymėjimą ir klasę, kuri būtų paveldima iš Veikla, o tada nepamirškite užregistruoti klasę manifeste – o ką, po velnių.
Tokiu atveju pasirinkite iš meniu failas | Naujas | veikla | pagrindinė veikla(ar kitą modelį). Tada pasirodys pažįstamas naujos veiklos kūrimo langas. Užpildykite reikiamus laukus.
Spustelėkite mygtuką Baigti ir veikla bus paruošta. Norėdami tai patikrinti, atidarykite manifesto failą ir patikrinkite, ar nėra naujo įrašo. Aš nekalbu apie klasės failus ir žymėjimą, jie pasirodys prieš jus.
Patys pridėkite naują mygtuką pagrindinės veiklos ekrane ir parašykite kodą, kad pereitumėte prie sukurtos veiklos.
Iš pradžių patarčiau rankiniu būdu sukurti visus būtinus komponentus naujai veiklai, kad suprastumėte klasės, žymėjimo ir manifesto ryšį. O kai atsidursite savo rankose, galite naudoti veiklos kūrimo vedlį, kad pagreitintumėte veiklą.
Duomenų perdavimas tarp veiklų
Norėdami iškviesti kitą veiklos ekraną, panaudojome paprasčiausią pavyzdį. Kartais reikia ne tik iškviesti naują ekraną, bet ir perkelti į jį duomenis. Pavyzdžiui, vartotojo vardas. Tokiu atveju turite naudoti specialią sritį papildomi duomenys, kurią turi klasė Tikslas.
Regionas papildomi duomenys yra porų sąrašas raktas/vertė, kuris perduodamas kartu su ketinimu. Stygos naudojamos kaip raktai, o reikšmėms galite naudoti bet kokius primityvius duomenų tipus, primityvų masyvus, klasių objektus ryšulėlis ir kt.
Norėdami perduoti duomenis kitai veiklai, naudokite metodą įdėtiExtra ():
Intent.putExtra("Raktas", "Vertė");
Gavimo veikla turėtų būti vadinama tinkamu metodu: getIntExtra (), getStringExtra() ir tt:
Int count = getIntent().getIntExtra("vardas", 0);
Pakartokime ankstesnį pavyzdį. Jau turime tris veiklas. Pirmoji veikla turės du teksto laukus ir mygtuką. Išvaizda gali būti tokia:
Antroje veikloje Antroji veikla nustatyti elementą teksto rodinys, kuriame rodysime iš pirmos veiklos gautą tekstą. Parašykime šį metodo kodą onCreate () antroje veikloje.
@Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); String user = "Gyvūnas"; String gift = "spurga skylė"; TextView infoTextView = (TextView)Id(RBy) .id.textViewInfo); infoTextView.setText(user + " , jums buvo suteikta " + dovana); )
Jei dabar paleisime programą ir tiesiog iškviesime antrąjį langą, kaip aprašyta pirmoje straipsnio dalyje, pamatysime numatytąjį užrašą ZhYvotnoe, tau buvo duota spurgos skylė. Sutikite, labai gaila gauti tokias žinutes.
Taisome situaciją. Pridėkite kodą prie pirmosios veiklos:
Public void onClick(View view) ( EditText userEditText = (EditText) findViewById(R.id.editTextUser); EditText giftEditText = (EditText) findViewById(R.id.editTextGift); Intent.intentMa =intent.intentisActivity, Secondity. klasė); // stumkite tekstą iš pirmojo teksto lauko į vartotojo vardo raktą intent.putExtra("naudotojo vardas", userEditText.getText().toString()); // stumkite tekstą iš antrojo teksto lauko į dovanos raktą intent.putExtra("dovana", dovanaEditText.getText().toString()); startActivity(intent); )
Įdėjome į specialų objektų konteinerį Tikslas du klavišai su reikšmėmis, paimtomis iš teksto laukų. Kai vartotojas įveda duomenis į teksto laukus, jie pateks į šį konteinerį ir bus perduoti antrajai veiklai.
Antroji veikla turėtų būti paruošta šiltai priimti pranešimus, kaip nurodyta toliau (paryškinta paryškintu šriftu).
// Numatytosios reikšmės String user = "LIFE"; Stygos dovana = "spurga skylė"; user = getIntent().getExtras().getString("naudotojo vardas"); dovana = getIntent().getExtras().getString("dovana"); TextView infoTextView = (TextView)findViewById(R.id.textViewInfo); infoTextView.setText(user + " , jums buvo suteikta " + dovana);
Dabar žinutė neatrodo tokia įžeidžianti, o kai kam net maloni. Sudėtinguose pavyzdžiuose pageidautina pridėti patvirtinimą apdorojant duomenis. Yra situacijų, kai pradedate antrą veiklą su tuščiais duomenimis, pvz nulinis, dėl kurios programa gali sugesti.
Mūsų atveju mes žinome, kad laukiame eilutės reikšmės, todėl kodą galima perrašyti taip:
intent intent = getIntent(); user = intent.getStringExtra("naudotojo vardas");
Vartotojas = getIntent().getStringExtra("naudotojo vardas");
Programa turi trūkumą – neaišku, iš ko gauname sveikinimus. Bet kuri gerai išauklėta beždžionė nepriims dovanos iš anoniminio šaltinio. Taigi, atlikdami namų darbus, pridėkite kitą teksto lauką, kad įvestumėte pranešimą siunčiančio vartotojo vardą.
„Google“ rekomenduoja naudoti šį raktų formatą: jūsų paketo pavadinimas kaip priešdėlis, po kurio nurodomas pats raktas. Tokiu atveju galite būti tikri, kad raktas yra unikalus sąveikaujant su kitomis programomis. Maždaug taip:
Vieša galutinė statinė eilutė USER = "ru.alexanderklimov.myapp.USER";
Kas įrėmino katiną Vaską – atgauname rezultatą
Ne visada pakanka tiesiog perduoti duomenis kitai veiklai. Kartais reikia gauti informaciją iš kitos veiklos, kai ji uždaryta. Jei anksčiau naudojome metodą startActivity (tikslas), tada yra susijęs metodas startActivityForResult(Intent intent, int RequestCode). Metodų skirtumas yra papildomame parametre prašymo kodas. Iš esmės tai tik sveikasis skaičius, kurį galite įsivaizduoti patys. Tai būtina norint atskirti, iš ko atėjo rezultatas. Tarkime, kad turite penkis papildomus ekranus ir jiems priskiriate reikšmes nuo 1 iki 5, o iš šio kodo galite nustatyti, kurio rezultatą reikia apdoroti. Galite naudoti reikšmę -1, tada ji bus lygiavertė metodo iškvietimui startActivity(), t.y. jokio rezultato nesulauksime.
Jei naudojate metodą startActivityForResult(), tada, norėdami gauti rezultatą, turite nepaisyti kode nurodyto metodo onActivityResult() ir apdoroti rezultatą. Supainioti? Pažvelkime į pavyzdį.
Tarkime, kad esate detektyvas. Gauta informacija, kad restorane nuo įtakingo asmens stalo pavogti du gabaliukai dešros ir kitų gaminių. Įtarimai krito trims įtariamiesiems – varnai, sušiktam šuniui ir katei Vaskai.
Vienas iš lankytojų pateikė nuotraukų seriją iš savo pontoninio „iPhone“:
Taip pat yra ir kito liudytojo parodymai: O Vaska klauso ir valgo.
Kuriame naują projektą Šerlokas su dviem veiklomis. Pirmajame ekrane bus mygtukas, skirtas perjungti į antrąjį ekraną, ir tekstinė etiketė, kurioje bus rodomas vagies vardas.
Antrame ekrane bus radijo mygtukų grupė:
Kadangi mes lauksime atsakymo iš antrojo ekrano, turime naudoti metodą startActivityForResult() pirmame ekrane, kuriame perduosime kintamąjį CHOOSE_THIEF kaip parametras prašymo kodas.
statinis galutinis privatus int CHOOSE_THIEF = 0; public void onClick(View v) ( Intent questionIntent = new Intent(MainActivity.this, ChooseActivity.class); startActivityForResult(questionIntent, CHOOSE_THIEF); )
Pažiūrėk į kodą. Kai spustelėsite mygtuką, dirbsime su antruoju ekranu Pasirinkite Veikla ir paleiskite antrąjį ekraną, laukiantį rezultato.
Pereiname į antrąjį ekraną ir parašysime antros veiklos kodą.
Viešas galutinis statinis String THIEF = "ru.alexanderklimov.sherlock.THIEF"; public void onRadioClick(View v) ( Intent answerIntent = new Intent(); jungiklis (v.getId()) ( atvejis R.id.radioDog: answerIntent.putExtra(THIEF, "Sušiktas šuo"); pertrauka; atvejis R.id .radioCrow: answerIntent.putExtra(THIEF, "Crow"); pertrauka; atvejis R.id.radioCat: answerIntent.putExtra(THHIEF, "Prževalskio arklys"); pertrauka; numatytasis: pertrauka; ) setResult(RESULT_OK, answerIntent); baigti ();)
Čia viskas paprasta, kai detektyvas pasirenka nusikaltėlio vardą, tada per metodą įdėtiExtra () perduodame rakto pavadinimą ir jo reikšmę.
Patogumui po pasirinkimo iškart uždarome antrą langą ir prieš uždarydami perduodame vertę RESULT_OK kad būtų aišku, kad pasirinkimas buvo priimtas. Jei vartotojas uždaro ekraną mygtuku Atgal, reikšmė bus perduota RESULT_CANCELED.
Metodas setResult() ima du parametrus: gautą kodą ir patį rezultatą, pavaizduotą kaip ketinimą. Gautas kodas nurodo, kokiu rezultatu veikla baigėsi, paprastai tai yra arba Veikla.RESULT_OK, arba Veikla.RESULT_CANCELED. Kai kuriais atvejais, norėdami tvarkyti konkrečios programos parinktis, turite naudoti savo grąžinimo kodą. Metodas setResult() palaiko bet kokią sveikojo skaičiaus reikšmę.
Jei per mygtuką aiškiai perduosite duomenis, būtų malonu pridėti metodą baigti() uždaryti antrąją veiklą kaip nereikalingą. Jei perėjimas įvyksta per mygtuką Atgal, tai nėra būtina.
Jei veiklą uždarė vartotojas, kai buvo paspaustas aparatūros grįžimo mygtukas, arba jei metodas baigti() buvo vadinamas prieš metodą setResult(), gautas kodas bus nustatytas į RESULT_CANCELED ir grąžintas ketinimas parodys vertę nulinis.
Grįžtame į pirmąjį ekraną. Pirmame ekrane laukiama atsakymo iš antrojo ekrano, todėl prie kodo reikia pridėti metodą onActivityResult().
@Nepaisyti apsaugotos tuštumos onActivityResult(int requestCode, int resultCode, Intent data) ( super.onActivityResult(requestCode, resultCode, data); TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); if (requestCode == CHOOSE_T) if (resultCode == REZULTATAS_OK) ( String thiefname = data.getStringExtra(ChooseActivity.THIEF); infoTextView.setText(thiefname); )else ( infoTextView.setText(""); // ištrinti tekstą ) ) )
Metodas tikisi gaunamų duomenų su kodu CHOOSE_THIEF, ir jei tokie duomenys gaunami, tada iš rakto išimama reikšmė Pasirinkite Veikla.VAGIS naudojant metodą getStringExtra. Išvedame gautą reikšmę į teksto rodinys(kintamasis infoTextView). Jei grįžome į ekraną per mygtuką Atgal, tada tiesiog ištriname tekstą.
Kai antrinė veikla uždaroma pirminiame komponente, tvarkytojas suaktyvina onActivityResult(). Prižiūrėtojas onActivityResult() užima kelis parametrus.
- Prašyti kodo. Kodas, naudojamas paleisti veiklą, kuri grąžina rezultatą
- Gautas kodas. Vaiko veiklos nustatytas rezultato kodas, nurodantis, kaip vaiko veikla baigėsi. Tai gali būti bet kokia sveikojo skaičiaus reikšmė, bet dažniausiai bet kuri Veikla.RESULT_OK, arba Veikla.RESULT_CANCELED
- Duomenys. Tikslas, naudojamas grąžinamiems duomenims supakuoti. Atsižvelgiant į antrinės veiklos tikslą, joje gali būti URI kelias, nurodantis pasirinktą turinio dalį. Arba (arba papildomai) vaiko veikla gali grąžinti informaciją kaip paprastas reikšmes, įtrauktas į tikslo parametrą priedai
Jei vaiko veikla netikėtai baigėsi arba prieš uždarant nebuvo nurodytas joks rezultato kodas, šis parametras taps lygus Veikla.RESULT_CANCELED.
Pradedame projektą, spustelėkite mygtuką ir einame į antrą ekraną. Ten pasirenkame vieną iš parinkčių. Jei pasirinksite varną, ekranas užsidarys ir pirmame ekrane bus rodomas nusikaltėlio vardas. Jei pasirinksite šunį, bus rodomas jo vardas.
Beje, jei pasirinksite katę, jos vardas nebus rodomas! Patikrinkite ir įsitikinkite patys. Paklausite kodėl? Elementarus Vatsonas! Pažeidėjas neatsižvelgė į vieną svarbią detalę. Restoranas buvo stebimas vaizdo kameromis, o įraše buvo matyti, kas iš tikrųjų pavogė dešrą ir įrėmino katę. Vaska, laikykis!
P.S. Jei iš pradžių kažkas atrodė nesuprantama, tada praktikuojant daug kas paaiškės. Duomenų perdavimas tarp ekranų yra įprastas programose, todėl pavyzdį išnagrinėsite ne kartą.
P.P.S. Geriausia žuvis yra dešra. Žinant šią silpnybę, katiną įrėminti nebuvo sunku.
Naudojant filtrus
Straipsnyje parodžiau įprastą būdą pereiti prie kitos veiklos, kai naudojamas metodas startActivity() nurodoma esama klasė ir klasė į perėjimą. Beje, veiklos klasė nebūtinai turi būti jūsų paraiškos dalis. Jei žinote klasės pavadinimą iš kitos programos, taip pat galite perjungti į ją. Tačiau galite pereiti prie kitos veiklos kitu būdu.
Rečiau praktikoje, bet naudinga. Tarkime, kad jau turite antrą veiklą. Apraše pridėkite prie jo specialų filtrą:
O antrąją veiklą pradedame mygtuko paspaudimu tokiu būdu.
Public void onClick(Rodyti rodinį) ( startActivity(new Intent("ru.alexanderklimov.testapplication.SecondActivity"); )
Pakeiskime ilgą eilutę konstanta.
Vieša statinė galutinė eilutė ACTION_SECOND_ACTIVITY = "ru.alexanderklimov.testapplication.SecondActivity"; public void onClick (Rodyti rodinį) ( startActivity(new Intent(ACTION_SECOND_ACTIVITY)); )
Taigi, ką mes padarėme. Antrajai veiklai užregistravome filtrą ir nurodėme pavadinimą veiksmas atribute android: vardas. Patogumo dėlei tiesiog įdėjau visą veiklos pavadinimą su paketo pavadinimu. Klasės konstruktorius Tikslas turi keletą perkrautų versijų. Vienoje versijoje galite nurodyti veiksmo eilutę. Nurodėme savo sukurtą veiksmą, kuris užregistruotas antroje veikloje. Sistema peržiūri visų įdiegtų programų manifestus veikimo metu. Ieškant atitikmens, sistema suranda mūsų filtrą ir paleidžia norimą veiklą.
Tuo pačiu principu galite pradėti ir kitą veiklą. Pažvelkite į pavyzdį. Jei nukopijuosite pavyzdį sau ir pažvelgsite į dokumentus android.provider.Settings.ACTION_AIRPLANE_MODE_SETTINGS, pamatysite, kad šis kodas atitinka eilutės konstantą public static final java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS". Palyginkite su mūsų kodu. Galite manyti, kad nustatymų veiklos neprisijungus filtre yra ši eilutė.
Filtro kategorijos pavadinimas android.intent.category.DEFAULT nurodo sistemai atlikti numatytąjį veiksmą, ty pradėti veiklą. Yra ir kitų vardų, kurie mūsų kol kas nedomina.
O dabar sudėtingas klausimas. Kas atsitiks, jei sukursite kitą veiklą ir nurodysite tą patį filtrą kaip ir antrąją veiklą? Ir patikrinkime. Sukurkite sau trečią veiklą ir į ją nukopijuokite bloką su filtru iš antrosios veiklos.
Pirmoje veikloje paspaudžiame mygtuką. Sistema paprašys pasirinkti norimą parinktį.
Jei pasirinksite elementą VISADA tada kitą kartą nereikės rinktis. Norėdami iš naujo nustatyti pasirinkimą, eikite į programos ypatybes nustatymuose ir raskite mygtuką aiškūs numatytieji nustatymai.
Veiklos pradžia pagal jos pavadinimą
Konstruktoriumi Tikslas Antrasis parametras yra klasė. Bet tarkime, kad yra kažkokia duomenų bazė, kurioje nurodyti veiklų pavadinimai ir reikia paleisti norimą veiklą pagal jos pavadinimą. Mes galime gauti pačią klasę pagal eilutės kintamąjį ir pradėti veiklą.
Pabandykite ( // Visas veiklos klasės pavadinimas String activityName = "ru.alexanderklimov.testapplication.SecondActivity"; // gauti Class Class objektą>myClass = Class.forName(veiklosPavadinimas); Intent intent = new Intent(this, myClass); startActivity(intent); ) sugauti (ClassNotFoundException e) ( e.printStackTrace(); )
Kažkaip turėjau užduotį perkelti duomenis iš tarnybos į veiklą. Pradėta ieškoti sprendimo standartiniame SDK, bet kadangi nebuvo laiko, priėmiau blogą sprendimą naudodamasis duomenų baze. Bet klausimas buvo atviras ir po kurio laiko aš supratau teisingesnį būdą, kuris yra SDK - naudojant Message, Handler, Messenger klases.
Idėja
Turime perkelti duomenis iš veiklos į paslaugą ir atvirkščiai. Kaip mes galime tai padaryti? Norėdami išspręsti savo problemą, mes jau turime viską, ko mums reikia. Viskas, ko reikia, yra susieti paslaugą su veikla naudojant bindService, perduoti reikiamus parametrus ir šiek tiek magijos naudojant pranešimų klases. Ir magija yra naudoti pranešimo egzempliorių kintamuosius ir ypač replyTo. Mums reikia šio kintamojo, kad galėtume pasiekti „Messanger“ paslaugos egzempliorių iš veiklos ir paslaugos „Messanger“ veiklos egzemplioriaus. Tiesą sakant, tai nėra taip paprasta. Bent jau mano ne itin gabiam protui. Iš dalies aš tik tobulinu jau esamą dokumentaciją – Paslaugos Be to, yra geras StackOverflow pavyzdys. Bet kokiu atveju, tikiuosi, kad straipsnis bus naudingas bent kažkam ir aš nedirbau veltui.
Pavyzdys
Pavyzdžiui, įdiegsime paslaugą, kuri padidins ir sumažins skaitiklio vertę ir grąžins rezultatą veikloje „TextView“. Išdėstymo kodą praleisiu, nes yra du mygtukai ir teksto laukas – viskas paprasta.
Įgyvendinimas
Štai visas aktyvinimo kodas:
Viešoji klasė „MainActivity“ išplečia veiklą (vieša statinė galutinė String TAG = "TestService"; TestServiceConnection testServConn; TextView testTxt; galutinis Messenger messenger = naujas Messenger(new IncomingHandler()); Messenger toServiceMessenger; @Override public void onCreate (B.tale) onCreate(savedInstanceState); setContentView(R.layout.activity_main); testTxt = (TextView)findViewById(R.id.test_txt); bindService(new Intent(this, TestService.class), (testServConn = naujas bandymo paslauga()),ContextContext() .BIND_AUTO_CREATE); ) @Nepaisyti viešosios void onDestroy()( super.onDestroy(); unbindService(testServConn); ) public void countIncrClick(View mygtukas)( Message msg = Message.obtain(null, TestService.COUNTre_PLUSp); Togly = Messenger; try ( toServiceMessenger.send(msg); ) catch (RemoteException e) ( e.printStackTrace(); ) ) public void countDecrClick(View mygtukas)( Message msg = Message.obtain(null, TestService.COUNT_MINUS); msg .replyTo = pasiuntinys; try ( toServiceMessenger.send(msg); ) catch (RemoteException e) ( e.printStackTrace(); ) ) private class IncomingHandler pratęsia Handler ( @Override public void handleMessage(Message msg)( switch (msg.what) ( case TestService. GET_COUNT: Log.d(TAG, "(activity)...get count"); testTxt.setText(""+msg.arg1); break; ) ) ) privati klasė TestServiceConnection įgyvendina ServiceConnection ( @Override public void onServiceConnected(ComponentName) pavadinimas, IBinder paslauga) ( toServiceMessenger = new Messenger(service); //nusiųskite pradinę skaitiklio reikšmę Message msg = Message.obtain(null, TestService.SET_COUNT); msg.replyTo = pasiuntinys; msg.arg1 = 0; //mūsų counter try ( toServiceMessenger.send(msg); ) catch (RemoteException e) (e.printStackTrace(); ) ) @Nepaisyti viešosios void onServiceDisconnected(ComponentName name) ( ) ) )
Leisk man paaiškinti. Kurdami veiklą, mes iš karto prisirišame prie paslaugos, įdiegdami ServiceConnection sąsają ir joje siunčiame žinutę „nustatykite skaitiklio vertę“, palikdami nulį ir sukurdami toServiceMessanger, perduodame konstruktoriui IBinder sąsają. Beje, šis egzempliorius turi būti grąžintas tarnyboje, kitaip bus NPE. Šios klasės pagalba siunčiame žinutes tarnybai. Ir čia tai magija – replyTo kintamajame išsaugome kitą savo Messenger egzempliorių – tą, kuris gauna atsakymą iš serverio ir būtent per jį bus palaikomas ryšys su veikla.
Norėdami gauti pranešimą iš tarnybos, naudojame savo tvarkyklę ir tiesiog ieškome mums reikalingų kintamųjų ir atliekame su jais veiksmus. Mygtukų paspaudimais (metodai countIncrClick, countDecrClick) siunčiame užklausas tarnybai, nurodydami norimą veiksmą kintamajame msg.what.
Paketas com.example.servicetest; importuoti android.app.Service; importuoti android.content.*; importuoti android.os.*; importuoti android.os.Procesas; importuoti android.util.Log; viešoji klasė „TestService“ išplečia paslaugą (viešas statinis galutinis int COUNT_PLUS = 1; viešas statinis galutinis int COUNT_MINUS = 2; viešas statinis galutinis int SET_COUNT = 0; viešas statinis galutinis int GET_COUNT = 3; int count = 0; IncomingHandler inHandler; Messenger messenger; Messenger toActivityMessenger; @Override public void onCreate()( super.onCreate(); HandlerThread gija = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); inHandler = new IncomingHandler(thread);megetssaLooper(gijos). = new Messenger(inHandler); ) @Nepaisyti viešo IBinder onBind(Intent arg0) ( grąžinti messsanger.getBinder(); ) @Nepaisyti public int onStartCommand(Intent intent, int flags, int startId) ( return START_STICKY; ) //pranešimo tvarkytojas veiklos privati klasė IncomingHandler išplečia Handler ( public IncomingHandler(Looper looper)( super(loooper); ) @Override public void handleMessage(Message msg)( //super.handleMessage(msg); toActivityMessenger = msg.replyTo; jungiklis (msg.what) ( atvejis SET_COUNT: count = msg.arg1; Log.d(MainActivity.TAG, "(service)...set count"); pertrauka; atvejis COUNT_PLUS: count++; Log.d(MainActivity.TAG , "(service)...count plus"); pertrauka; atvejis COUNT_MINUS: Log.d(MainActivity.TAG, "(service)...count minus"); count--; break; ) //skaitiklio siuntimas reikšmė veikloje Pranešimas outMsg = Message.obtain(inHandler, GET_COUNT); outMsg.arg1 = skaičius; outMsg.replyTo = pasiuntinys; try ( if(toActivityMessenger != null) toActivityMessenger.send(outMsg); ) gaudyti (RemoteException e) ( e.printStackTrace(); ) ) ) )
Viskas pagal analogiją su veiklos logika. Net nežinau, ar man reikia ką nors paaiškinti. Vienintelis dalykas yra tai, kad aš nedelsdamas siunčiu užklausą atgal į HandMessages veiklą, naudodamas magic replyTo kintamąjį ir ištraukdamas norimą Messenger aukščiau. Ir antras dalykas, kurį jau minėjau, yra:
@Nepaisyti viešo IBinder onBind(Intent arg0) ( grąžinti messsanger.getBinder(); )
be kurio viskas nukris. Būtent šis sąsajos egzempliorius bus perduotas ServiceConnection
Išvada
Apskritai. Toks sugalvotas veiklos ir paslaugos sąveikos pavyzdys. Man tai atrodo gana nebanali sąveika, nors kažkam gali atrodyti kitaip.
Klausimai, paaiškinimai ir kt. Dėl kokių nors aspektų gali būti netikslumų, todėl drąsiai rašykite ir pataisykite.
Tikiuosi, kad įrašas buvo naudingas skaitytojams.