აპლიკაცია ყოველთვის არ შედგება ერთი ეკრანისგან. მაგალითად, ჩვენ შევქმენით ძალიან სასარგებლო პროგრამადა მომხმარებელს სურს იცოდეს ვინ არის ავტორი. ის აჭერს ღილაკს „შესახებ“ და ხვდება ახალ ეკრანზე, სადაც არის სასარგებლო ინფორმაცია პროგრამის ვერსიის, ავტორის, საიტის მისამართის, რამდენი კატა ჰყავს ავტორს და ა.შ. წარმოიდგინეთ აქტივობის ეკრანი, როგორც ვებ გვერდი სხვა გვერდის ბმულით. თუ დააკვირდებით ფაილში არსებულ კოდს MainActivity.javaწინა გაკვეთილებიდან ნახავთ, რომ ჩვენი კლასი Მთავარი აქტივობაასევე ეხება აქტივობა(ან მისი მემკვიდრეები) ან, უფრო სწორად, მისგან არის მემკვიდრეობით მიღებული.
საჯარო კლასის MainActivity აფართოებს AppCompatActivity
როგორც თქვენ მიხვდით, ჩვენ უნდა შევქმნათ ახალი კლასი, რომელიც შეიძლება გამოიყურებოდეს Მთავარი აქტივობადა შემდეგ როგორღაც გადაერთეთ მასზე ღილაკზე დაჭერით.
ექსპერიმენტისთვის ავიღებთ პროგრამას პირველი გაკვეთილიდან და გამოვიყენებთ ღილაკს ექსპერიმენტებისთვის (ან შექმნა ახალი პროექტიეკრანზე ერთი ღილაკით). შემდეგი, მოდით შევქმნათ ახალი ფორმაჩვენება გამოსადეგი ინფორმაცია. მაგალითად, მოდით ვაჩვენოთ მომხმარებელს რას აკეთებს კატა, როდესაც ის მიდის მარცხნივ და მარჯვნივ. გეთანხმები, ძალიან მნიშვნელოვანი ინფორმაცია, რომელიც იძლევა სამყაროს ამოხსნის გასაღებს.
ჩვენ შევქმნით ახალ აქტივობას ხელით, თუმცა სტუდიას აქვს მზა შაბლონები. მაგრამ არაფერია რთული და უკეთესი გაგებისთვის სასარგებლოა ყველაფრის ხელით გაკეთება.
მოდით შევქმნათ ახალი XML მარკირების ფაილი activity_about.xmlსაქაღალდეში რეს/განლაგება. დააწკაპუნეთ საქაღალდეზე მარჯვენა ღილაკით განლაგებადა აირჩიე კონტექსტური მენიუ ახალი | განლაგების რესურსის ფაილი. გამოჩნდება დიალოგური ფანჯარა. შეიყვანეთ ფაილის სახელი პირველ ველში აქტივობა_დაახლოებით. მეორეში, თქვენ უნდა შეიყვანოთ root ელემენტი. ნაგულისხმევად არის იქ ConstraintLayout. წაშალე ტექსტი და შეიყვანე გადახვევის ხედი. რამდენიმე სიმბოლოს შეყვანა საკმარისია იმისთვის, რომ სტუდიამ შემოგთავაზოს მზა ვარიანტები, შეგიძლიათ დაუყოვნებლივ დააჭიროთ Enter სიტყვის სრული შეყვანის მოლოდინის გარეშე:
ვიღებთ შესაბამის ბლანკს, რომელშიც ჩავსვით ელემენტი ტექსტის ხედვა.
ინფორმაცია იქნება მოძიებული რესურსებიდან, კერძოდ სიმებიანი რესურსიდან შესახებ_ტექსტი. ახლა ის წითლად არის მონიშნული, რაც მიუთითებს ინფორმაციის არარსებობაზე. შეიძლება დაჭერა Alt+Enterდა შეიყვანეთ ტექსტი დიალოგურ ფანჯარაში. მაგრამ ჩვენი მაგალითისთვის, ეს მეთოდი არ იმუშავებს, რადგან ჩვენი ტექსტი იქნება მრავალხაზოვანი, საკონტროლო სიმბოლოების გამოყენებით. ასე რომ მოდი სხვანაირად მოვიქცეთ. მოდით გავხსნათ ფაილი res/values/strings.xmlდა ხელით შეიყვანეთ შემდეგი ტექსტი:
ჩვენ გამოვიყენეთ უმარტივესი HTML ტექსტის ფორმატირების ტეგები, როგორიცაა , , . ჩვენი მაგალითისთვის, საკმარისია თამამი სიტყვებით, რომლებიც ეხება კატას და მოძრაობის მიმართულებას. ტექსტის თარგმნა ახალი ხაზიგამოიყენეთ სიმბოლოები \n. მოდით დავამატოთ კიდევ ერთი სიმებიანი რესურსი ახალი ეკრანის სათაურისთვის:
გასაგებია მარკირებით. შემდეგი, თქვენ უნდა შექმნათ კლასი ფანჯრისთვის Activity.java-ს შესახებ. აირჩიეთ მენიუდან ფაილი | ახალი | ჯავის კლასიდა შეავსეთ საჭირო ველები. თავდაპირველად საკმარისია მხოლოდ სახელის მითითება. მერე სხვა სფეროებს შეეხო.
მოდი მივიღოთ მომზადება.
ახლა საკლასო ოთახი თითქმის ცარიელია. მოდით დავამატოთ კოდი ხელით. კლასმა უნდა მიიღოს მემკვიდრეობა აბსტრაქტული კლასისგან აქტივობაან მისი ნათესავები ფრაგმენტული აქტივობა, AppCompatActivityდა ა.შ. დამატება აგრძელებს აქტივობას. აქტივობის კლასს უნდა ჰქონდეს მეთოდი onCreate (). ჩადეთ მაუსის კურსორი კლასში და აირჩიეთ მენიუდან კოდი | უგულებელყოფის მეთოდები(Ctrl+O). დიალოგურ ფანჯარაში ჩვენ ვეძებთ სასურველ კლასს, შეგიძლიათ აკრიფოთ პირველი სიმბოლოები კლავიატურაზე სწრაფი ძებნა. შექმნილ მეთოდში, თქვენ უნდა გამოძახოთ მეთოდი setContentView(), რომელიც ჩატვირთავს მომზადებულ მარკირებას ეკრანზე. ჩვენ გვექნება ასეთი ვარიანტი.
პაკეტი en.alexanderklimov.helloworld; იმპორტი android.app.Activity; იმპორტი android.os.Bundle; /** * შექმნილია ალექსანდრე კლიმოვის მიერ 12/01/2014. */ საჯარო კლასი AboutActivity აფართოებს აქტივობას ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_about); ) )
ახლა ყველაზე მთავარი იწყება. ჩვენი ამოცანაა გადავიდეთ ახალ ეკრანზე პირველ ეკრანზე ღილაკზე დაჭერისას. დავუბრუნდეთ კლასს Მთავარი აქტივობა. მოდით დავწეროთ ღილაკზე დაწკაპუნების დამმუშავებელი:
საჯარო void onClick(View view) ( Intent intent = new Intent (MainActivity.this, AboutActivity.class); startActivity(intent); )
აქ გამოვიყენე გაკვეთილზე აღწერილი ღილაკზე დაჭერის მეთოდი.
ახალი ეკრანის დასაწყებად, თქვენ უნდა შექმნათ კლასის მაგალითი განზრახვადა მიუთითეთ მიმდინარე კლასი პირველ პარამეტრში, ხოლო კლასი გადასვლისთვის მეორეში, გვაქვს ეს აქტივობის შესახებ. ამის შემდეგ მეთოდს ეძახიან startActivity (), რომელიც უშვებს ახალ ეკრანს.
თუ ახლა ცდილობთ აპლიკაციის ტესტირებას ემულატორში, მიიღებთ შეცდომის შეტყობინებას. რა დავაშავეთ? ერთი მნიშვნელოვანი ნაბიჯი გამოგვრჩა. თქვენ უნდა დაარეგისტრიროთ ახალი აქტივობამანიფესტში AndroidManifest.xml. იპოვეთ ეს ფაილი თქვენს პროექტში და ორჯერ დააწკაპუნეთ მასზე. გაიხსნება ფაილის რედაქტირების ფანჯარა. დაამატეთ ახალი ტეგი
ეს არის ის, სადაც სიმებიანი რესურსი გამოდგება შესახებ_სათაური. გაუშვით აპლიკაცია, დააჭირეთ ღილაკს და მიიღეთ ფანჯარა პროგრამის შესახებ. ამრიგად, ჩვენ ვისწავლეთ როგორ შევქმნათ ახალი ფანჯარა და მოვუწოდოთ მას ღილაკზე დაჭერით. და ჩვენს განკარგულებაში გამოჩნდა მეგა-მოხერხებული პროგრამა - ახლა ყოველთვის იქნება მინიშნება, თუ რას აკეთებს კატა, როდესაც ის მარცხნივ მიდის.
კიდევ ერთხელ ვამახვილებ თქვენს ყურადღებას იმ ფაქტზე, რომ მეორე შექმნილი აქტივობის კლასი უნდა იყოს მემკვიდრეობით მიღებული კლასიდან აქტივობაან მსგავსი ( List Activityდა ა.შ.), გქონდეთ XML მარკირების ფაილი (საჭიროების შემთხვევაში) და ჩაიწეროს manifest-ში.
მეთოდის გამოძახების შემდეგ startActivity ()დაიწყება ახალი აქტივობა (ამ შემთხვევაში აქტივობის შესახებ), ის გახდება ხილული და გადავა დატის ზედა ნაწილში, რომელიც შეიცავს გაშვებულ კომპონენტებს. მეთოდის გამოძახებისას დასრულება ()ახალი აქტივობიდან (ან როდესაც ტექნიკის უკანა ღილაკზე დაჭერით) ის დაიხურება და წაიშლება დასტადან. დეველოპერს ასევე შეუძლია ნავიგაცია წინა (ან სხვა) აქტივობაზე იმავე მეთოდის გამოყენებით startActivity ().
მესამე ეკრანის შექმნა - გზა ზარმაცებისთვის
პროგრამისტები, კატების მსგავსად, ზარმაცი არსებები არიან. ყოველთვის გახსოვდეთ, რომ აქტივობისთვის თქვენ უნდა შექმნათ მარკირება და კლასი, რომელიც მემკვიდრეობით იღებს აქტივობა, და შემდეგ არ დაგავიწყდეთ კლასის რეგისტრაცია მანიფესტში - ოჰ, რა ჯანდაბა.
ამ შემთხვევაში აირჩიეთ მენიუდან ფაილი | ახალი | საქმიანობა | ძირითადი საქმიანობა(ან სხვა ნიმუში). შემდეგი, გამოჩნდება ნაცნობი ფანჯარა ახალი აქტივობის შესაქმნელად. შეავსეთ საჭირო ველები.
დააჭირეთ ღილაკს დასრულებადა აქტივობა მზად იქნება. ამის დასადასტურებლად გახსენით manifest ფაილი და შეამოწმეთ ახალი ჩანაწერი. კლასის ფაილებზე და მარკირებაზე არ ვსაუბრობ, ისინი თქვენს თვალწინ გამოჩნდებიან.
თავად დაამატეთ ახალი ღილაკი ძირითადი აქტივობის ეკრანზე და დაწერეთ კოდი შექმნილ აქტივობაზე გადასასვლელად.
თავდაპირველად, გირჩევთ, ხელით შექმნათ ყველა საჭირო კომპონენტი ახალი აქტივობისთვის, რათა გაიგოთ კლასს, მარკირებასა და მანიფესტს შორის ურთიერთობა. და როცა ხელთ მიიღებთ, შეგიძლიათ გამოიყენოთ აქტივობის შექმნის ოსტატი, რათა დააჩქაროთ საქმეები.
მონაცემთა გადაცემა აქტივობებს შორის
ჩვენ გამოვიყენეთ უმარტივესი მაგალითი სხვა აქტივობის ეკრანის გამოსაძახებლად. ზოგჯერ საჭიროა არა მხოლოდ ახალი ეკრანის გამოძახება, არამედ მასზე მონაცემების გადაცემა. მაგალითად, მომხმარებლის სახელი. ამ შემთხვევაში, თქვენ უნდა გამოიყენოთ სპეციალური ტერიტორია დამატებითი მონაცემები, რომელიც კლასს აქვს განზრახვა.
რეგიონი დამატებითი მონაცემებიარის წყვილების სია გასაღები/მნიშვნელობა, რომელიც გადის განზრახვასთან ერთად. სტრიქონები გამოიყენება გასაღებად, ხოლო მნიშვნელობებისთვის შეგიძლიათ გამოიყენოთ ნებისმიერი პრიმიტიული მონაცემთა ტიპი, პრიმიტივების მასივები, კლასის ობიექტები. შეკვრადა ა.შ.
სხვა აქტივობაზე მონაცემების გადასაცემად გამოიყენეთ მეთოდი putExtra ():
Intent.putExtra ("Key", "Value");
მიმღებმა აქტივობამ უნდა მოითხოვოს შესაბამისი მეთოდი: getIntExtra (), getStringExtra ()და ა.შ.:
Int count = getIntent().getIntExtra("სახელი", 0);
მოდით გადავხედოთ წინა მაგალითს. სამი აქტივობა უკვე გვაქვს. პირველ აქტივობას ექნება ორი ტექსტური ველი და ღილაკი. გარეგნობა შეიძლება იყოს შემდეგი:
მეორე აქტივობაზე მეორე აქტივობაელემენტის დაყენება ტექსტის ხედვა, რომელშიც გამოვაჩენთ პირველი აქტივობიდან მიღებულ ტექსტს. მოდით დავწეროთ შემდეგი კოდი მეთოდისთვის onCreate ()მეორე აქტივობაზე.
@Override დაცული void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); სიმებიანი მომხმარებელი = "ცხოველი"; სიმებიანი საჩუქარი = "დონატის ხვრელი"; TextView infoTextViewdT .id.textViewInfo); infoTextView.setText(მომხმარებელი + " , მოგცეს " + საჩუქარი); )
თუ ახლა გავუშვით პროგრამა და უბრალოდ გამოვიძახებთ მეორე ფანჯარას, როგორც ეს აღწერილია სტატიის პირველ ნაწილში, დავინახავთ ნაგულისხმევ წარწერას. ZhYvotnoe, თქვენ მოგცეს დონატ ხვრელი. დამეთანხმებით, სირცხვილია ასეთი შეტყობინებების მიღება.
ჩვენ ვასწორებთ სიტუაციას. დაამატეთ კოდი პირველ აქტივობას:
საჯარო void onClick(View view) ( EditText userEditText = (EditText) findViewById(R.id.editTextUser); EditText giftEditText = (EditText) findViewById(R.id.editTextGift); Intent intent = newActivity. class); // გადაიტანეთ ტექსტი პირველი ტექსტის ველიდან მომხმარებლის სახელის კლავიშში intent.putExtra("username", userEditText.getText().toString()); // გადაიტანეთ ტექსტი მეორე ტექსტის ველიდან საჩუქრის გასაღებში intent.putExtra("საჩუქარი", giftEditText.getText().toString()); startActivity(intent); )
ჩვენ მოვათავსეთ სპეციალური ობიექტის კონტეინერში განზრახვაორი ღილაკი ტექსტის ველებიდან აღებული მნიშვნელობებით. როდესაც მომხმარებელი შეიტანს მონაცემებს ტექსტურ ველებში, ისინი მოხვდება ამ კონტეინერში და გადაეცემა მეორე აქტივობას.
მეორე აქტივობა მზად უნდა იყოს თბილად მიიღოს შემდეგი შეტყობინებები (მონიშნულია თამამად).
// ნაგულისხმევი მნიშვნელობები String user = "LIFE"; სიმებიანი საჩუქარი = "დონატ ხვრელი"; მომხმარებელი = getIntent().getExtras().getString("მომხმარებლის სახელი"); gift = getIntent().getExtras().getString("საჩუქარი"); TextView infoTextView = (TextView)findViewById(R.id.textViewInfo); infoTextView.setText(მომხმარებელი + " , მოგცეს " + საჩუქარი);
ახლა მესიჯი არც ისე შეურაცხმყოფელი, მაგრამ ზოგიერთისთვის სასიამოვნოც კი გამოიყურება. რთულ მაგალითებში სასურველია დაემატოს ვალიდაცია მონაცემთა დამუშავებისას. არის სიტუაციები, როდესაც მეორე აქტივობას იწყებ ცარიელი მონაცემებით, როგორიცაა null, რამაც შეიძლება დააზიანოს აპლიკაცია.
ჩვენს შემთხვევაში, ჩვენ ვიცით, რომ ველოდებით სტრიქონის მნიშვნელობას, ამიტომ კოდი შეიძლება გადაიწეროს შემდეგნაირად:
intent intent = getIntent(); user = intent.getStringExtra ("მომხმარებლის სახელი");
მომხმარებელი = getIntent().getStringExtra("მომხმარებლის სახელი");
პროგრამას აქვს ნაკლი - გაუგებარია ვისგან ვიღებთ მისალმებებს. ნებისმიერი კეთილგანწყობილი მაიმუნი არ მიიღებს საჩუქარს ანონიმური წყაროსგან. ასე რომ, როგორც საშინაო დავალება, დაამატეთ სხვა ტექსტური ველი, რომ შეიყვანოთ მომხმარებლის სახელი, რომელიც აგზავნის შეტყობინებას.
Google გირჩევთ გამოიყენოთ შემდეგი ფორმატი გასაღებებისთვის: თქვენი პაკეტის სახელი, როგორც პრეფიქსი, რასაც მოჰყვება თავად გასაღები. ამ შემთხვევაში, შეგიძლიათ დარწმუნებული იყოთ, რომ გასაღები უნიკალურია სხვა აპლიკაციებთან ურთიერთობისას. დაახლოებით ასე:
საჯარო საბოლოო სტატიკური String USER = "ru.alexanderklimov.myapp.USER";
ვინ მოაწყო კატა ვასკა - ჩვენ ვიღებთ შედეგს უკან
ყოველთვის არ არის საკმარისი მონაცემების უბრალოდ გადაცემა სხვა აქტივობაზე. ზოგჯერ გჭირდებათ ინფორმაციის დაბრუნება სხვა აქტივობიდან, როდესაც ის დახურულია. თუ ადრე მეთოდს ვიყენებდით startActivity (განზრახვა), მაშინ არის დაკავშირებული მეთოდი startActivityFor Result (განზრახვა, int RequestCode). მეთოდებს შორის განსხვავება მდგომარეობს დამატებით პარამეტრში მოთხოვნის კოდი. ეს ძირითადად მხოლოდ მთელი რიცხვია, რომელიც შეგიძლიათ იფიქროთ საკუთარ თავზე. აუცილებელია იმის გასარკვევად, თუ ვისგან მოვიდა შედეგი. ვთქვათ, თქვენ გაქვთ ხუთი დამატებითი ეკრანი და ანიჭებთ მათ მნიშვნელობებს 1-დან 5-მდე და ამ კოდიდან შეგიძლიათ განსაზღვროთ ვისი შედეგის დამუშავება გჭირდებათ. შეგიძლიათ გამოიყენოთ მნიშვნელობა -1, მაშინ ეს იქნება მეთოდის გამოძახების ტოლფასი startActivity (), ე.ი. შედეგს ვერ მივიღებთ.
თუ თქვენ იყენებთ მეთოდს startActivityFor Result(), მაშინ შედეგის მისაღებად კოდის მეთოდის გადაფარვა გჭირდებათ onActivityResult()და დაამუშავეთ შედეგი. დაბნეული? მოდით შევხედოთ მაგალითს.
ვთქვათ, რომ დეტექტივი ხარ. ცნობილი გახდა, რომ რესტორანში გავლენიანი პირის მაგიდიდან ორი ცალი ძეხვი და სხვა პროდუქტი მოიპარეს. ეჭვი დაეცა სამ ეჭვმიტანილზე - ყვანაზე, გარყვნილ ძაღლსა და კატა ვასკას.
ერთ-ერთმა ვიზიტორმა მოგვაწოდა ფოტოების სერია მისი პონტონური iPhone-დან:
ასევე არის სხვა მოწმის ჩვენება: და ვასკა უსმენს და ჭამს.
ჩვენ ვქმნით ახალ პროექტს შერლოკიორი აქტივობით. პირველ ეკრანზე იქნება ღილაკი მეორე ეკრანზე გადასასვლელად და ტექსტური ეტიკეტი, რომელიც გამოსახავს ქურდის სახელს.
მეორე ეკრანზე იქნება რადიო ღილაკების ჯგუფი:
ვინაიდან ჩვენ ველოდებით პასუხს მეორე ეკრანიდან, უნდა გამოვიყენოთ მეთოდი startActivityFor Result()პირველ ეკრანზე, სადაც გადავიტანთ ცვლადს CHOOSE_THIEFროგორც პარამეტრი მოთხოვნის კოდი.
სტატიკური საბოლოო პირადი int CHOOSE_THIEF = 0; public void onClick(View v) ( Intent questionIntent = new Intent(MainActivity.this, ChooseActivity.class); startActivityForResult(questionIntent, CHOOSE_THIEF); )
შეხედე კოდს. როდესაც დააჭირეთ ღილაკს, ჩვენ ვაპირებთ მუშაობას მეორე ეკრანზე აირჩიეთ აქტივობადა გაუშვით მეორე ეკრანი შედეგის მოლოდინში.
გადავდივართ მეორე ეკრანზე და დავწერთ მეორე აქტივობის კოდს.
საჯარო საბოლოო სტატიკური String THIEF = "ru.alexanderklimov.sherlock.THIEF"; public void onRadioClick(View v) ( Intent answerIntent = new Intent(); switch (v.getId()) ( case R.id.radioDog: answerIntent.putExtra (THIEF, "Fucking Dog"); break; case R.id .radioCrow: answerIntent.putExtra(THIEF, "Crow"); break; case R.id.radioCat: answerIntent.putExtra(THIEF, "Przewalski's Horse"); break; ნაგულისხმევი: break; ) setResult(RESULT_OK, answerIntent); დასრულება ();)
აქ ყველაფერი მარტივია, როცა დეტექტივი კრიმინალის სახელს ირჩევს, მერე მეთოდით putExtra ()ჩვენ გადავცემთ გასაღების სახელს და მის მნიშვნელობას.
მოხერხებულობისთვის, შერჩევის შემდეგ, ჩვენ დაუყოვნებლივ ვხურავთ მეორე ფანჯარას და გადავცემთ მნიშვნელობას დახურვამდე RESULT_OKრათა ნათელი გახდეს, რომ არჩევანი გაკეთდა. თუ მომხმარებელი დახურავს ეკრანს უკან ღილაკის საშუალებით, მნიშვნელობა გადაეცემა RESULT_CANCELED.
მეთოდი setResult()იღებს ორ პარამეტრს: მიღებულ კოდს და თავად შედეგს, რომელიც წარმოდგენილია როგორც განზრახვა. მიღებული კოდი ამბობს, რა შედეგით დასრულდა აქტივობა, როგორც წესი, ეს არის ან აქტივობა.RESULT_OK, ან აქტივობა.RESULT_CANCELED. ზოგიერთ შემთხვევაში, თქვენ უნდა გამოიყენოთ თქვენი დაბრუნების კოდი აპლიკაციის სპეციფიკური ვარიანტების დასამუშავებლად. მეთოდი setResult()მხარს უჭერს ნებისმიერ მთელ მნიშვნელობას.
თუ ღილაკზე პირდაპირ გადასცემთ მონაცემებს, კარგი იქნებოდა მეთოდის დამატება დასრულება ()დახუროს მეორე აქტივობა, როგორც არასაჭირო. თუ გადასვლა ხდება უკან ღილაკის საშუალებით, მაშინ ეს არ არის საჭირო.
თუ აქტივობა დაიხურა მომხმარებლის მიერ, როდესაც ტექნიკის უკანა ღილაკი დააჭირა, ან თუ მეთოდი დასრულება ()გამოიძახეს მეთოდის წინ setResult(), შედეგად კოდი დაყენდება RESULT_CANCELEDდა დაბრუნებული განზრახვა აჩვენებს მნიშვნელობას null.
ჩვენ ვუბრუნდებით პირველ ეკრანს. პირველი ეკრანი ელოდება პასუხს მეორე ეკრანიდან, ასე რომ თქვენ უნდა დაამატოთ მეთოდი კოდში onActivityResult().
@Override დაცული void onActivityResult(int requestCode, int resultCode, intent data) ( super.onActivityResult(requestCode, resultCode, data); TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); თუ (CH)CodeCode =IE if (resultCode == RESULT_OK) (string thiefname = data.getStringExtra (ChooseActivity.THIEF); infoTextView.setText(thiefname); )else (infoTextView.setText(""); // წაშალე ტექსტი) )
მეთოდი ელოდება შემომავალ მონაცემებს კოდით CHOOSE_THIEF, და თუ ასეთი მონაცემები მოდის, მაშინ ამოიღებს მნიშვნელობას გასაღებიდან აირჩიეთActivity.THIEFმეთოდის გამოყენებით getStringExtra. ჩვენ გამოვაქვთ მიღებული მნიშვნელობა ტექსტის ხედვა(ცვლადი infoTextView). თუ ჩვენ დავუბრუნდით ეკრანს უკან ღილაკის საშუალებით, მაშინ უბრალოდ ვშლით ტექსტს.
როდესაც ბავშვის აქტივობა დახურულია მშობლის კომპონენტში, დამმუშავებელი მუშაობს onActivityResult(). დამმუშავებელი onActivityResult()იღებს რამდენიმე პარამეტრს.
- მოითხოვეთ კოდი. კოდი, რომელიც გამოიყენება აქტივობის დასაწყებად, რომელიც აბრუნებს შედეგს
- შედეგად მიღებული კოდი. ბავშვის აქტივობის მიერ დაყენებული შედეგის კოდი, რომელიც მიუთითებს იმაზე, თუ როგორ დასრულდა ბავშვის აქტივობა. ეს შეიძლება იყოს ნებისმიერი მთელი რიცხვი, მაგრამ როგორც წესი აქტივობა.RESULT_OK, ან აქტივობა.RESULT_CANCELED
- მონაცემები. განზრახვა, რომელიც გამოიყენება დაბრუნებული მონაცემების შესაფუთად. ბავშვის აქტივობის მიზნიდან გამომდინარე, ის შეიძლება შეიცავდეს URI გზას, რომელიც წარმოადგენს კონტენტის არჩეულ ნაწილს. ალტერნატიულად (ან დამატებით), ბავშვის აქტივობას შეუძლია დააბრუნოს ინფორმაცია, როგორც მარტივი მნიშვნელობები, რომლებიც შეფუთულია განზრახვის პარამეტრში. დამატებები
თუ ბავშვის აქტივობა მოულოდნელად დასრულდა, ან თუ მის დახურვამდე შედეგის კოდი არ იყო მითითებული, ეს პარამეტრი გახდება ტოლი აქტივობა.RESULT_CANCELED.
ვიწყებთ პროექტს, ვაჭერთ ღილაკს და გადავდივართ მეორე ეკრანზე. იქ ვირჩევთ ერთ-ერთ ვარიანტს. თუ ყვავი აირჩევთ, ეკრანი დაიხურება და პირველ ეკრანზე გამოჩნდება დამნაშავეს სახელი. თუ ძაღლს აირჩევთ, მისი სახელი გამოჩნდება.
სხვათა შორის, თუ კატას აირჩევთ, მისი სახელი არ გამოჩნდება! შეამოწმეთ და თავად დარწმუნდებით. იკითხავთ რატომ? ელემენტარული უოტსონი! დამნაშავემ ერთი მნიშვნელოვანი დეტალი არ გაითვალისწინა. რესტორანს ვიდეოკამერების მეთვალყურეობა ექვემდებარებოდა და ჩანაწერმა აჩვენა, ვინ მოიპარა სინამდვილეში ძეხვი და კატის ჩარჩოში ჩასვა. ვასკა, მოითმინე!
P.S. თუ თავიდან რაღაც გაუგებარი ჩანდა, მაშინ პრაქტიკით ბევრი რამ გაირკვევა. ეკრანებს შორის მონაცემების გადაცემა ხშირია აპლიკაციებში და თქვენ მაგალითს არაერთხელ შეისწავლით.
P.P.S. საუკეთესო თევზი ძეხვია. ამ სისუსტის ცოდნით, კატის ჩარჩოში მოქცევა რთული არ იყო.
ფილტრების გამოყენება
სტატიაში მე ვაჩვენე ჩვეულებრივი გზა სხვა აქტივობაზე გადასვლის მეთოდის დროს startActivity ()მითითებულია მიმდინარე კლასი და კლასი გადასვლაზე. სხვათა შორის, აქტივობის კლასი არ უნდა იყოს თქვენი განაცხადის ნაწილი. თუ თქვენ იცით კლასის სახელი სხვა აპლიკაციიდან, შეგიძლიათ გადახვიდეთ მასზეც. მაგრამ თქვენ შეგიძლიათ სხვა აქტივობაზე გადახვიდეთ სხვა გზით.
პრაქტიკაში ნაკლებად გავრცელებული, მაგრამ სასარგებლო. ვთქვათ, თქვენ უკვე გაქვთ მეორე აქტივობა. manifest-ში დაამატეთ მას სპეციალური ფილტრი:
და ჩვენ ვიწყებთ მეორე აქტივობას ამ გზით ღილაკის დაჭერით.
საჯარო void onClick(View view) ( startActivity(new Intent("ru.alexanderklimov.testapplication.SecondActivity"); )
მოდით შევცვალოთ გრძელი სტრიქონი მუდმივით.
საჯარო სტატიკური საბოლოო სტრიქონი ACTION_SECOND_ACTIVITY = "ru.alexanderklimov.testapplication.SecondActivity"; საჯარო void onClick(View view) ( startActivity(new Intent(ACTION_SECOND_ACTIVITY)); )
მაშ რა გავაკეთეთ. მეორე აქტივობისთვის ჩვენ დავარეგისტრირეთ ფილტრი და დავასახელეთ სახელი მოქმედებაატრიბუტში android: name. მოხერხებულობისთვის, მე მასში ჩავდე აქტივობის სრული სახელწოდება პაკეტის სახელთან ერთად. კლასის კონსტრუქტორი განზრახვააქვს რამდენიმე გადატვირთული ვერსია. ერთ ვერსიაში შეგიძლიათ მიუთითოთ სტრიქონი მოქმედებისთვის. ჩვენ მივუთითეთ ჩვენი შექმნილი აქცია, რომელიც რეგისტრირებულია მეორე აქტივობაში. სისტემა უყურებს ყველა დაინსტალირებული აპლიკაციის მანიფესტებს ოპერაციის დროს. მატჩის ძიებისას სისტემა პოულობს ჩვენს ფილტრს და იწყებს სასურველ აქტივობას.
ამავე პრინციპით შეგიძლიათ დაიწყოთ სხვა აქტივობები. შეხედე მაგალითს. თუ თქვენ დააკოპირებთ მაგალითს საკუთარ თავს და გადახედეთ დოკუმენტაციას android.provider.Settings.ACTION_AIRPLANE_MODE_SETTINGS, ნახავთ, რომ ეს კოდი შეესაბამება სტრიქონის მუდმივას საჯარო სტატიკური საბოლოო java.lang.String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS". შეადარეთ ჩვენს კოდს. შეგიძლიათ ვივარაუდოთ, რომ ოფლაინ რეჟიმში პარამეტრების აქტივობას ეს ხაზი აქვს ფილტრში.
ფილტრის კატეგორიის სახელი android.intent.category.DEFAULTეუბნება სისტემას განახორციელოს ნაგულისხმევი მოქმედება, რომელიც არის აქტივობის დაწყება. არის სხვა სახელები, რომლებიც ჯერ არ გვაინტერესებს.
ახლა კი რთული კითხვა. რა მოხდება, თუ შექმნით სხვა აქტივობას და მიუთითებთ იგივე ფილტრს, როგორც მეორე აქტივობას? და შევამოწმოთ. შექმენით მესამე აქტივობა თქვენთვის და დააკოპირეთ ბლოკი ფილტრით მეორე აქტივობიდან მასში.
პირველ აქტივობაში ვაჭერთ ღილაკს. სისტემა მოგთხოვთ აირჩიოთ სასურველი ვარიანტი.
თუ ნივთს აირჩევთ ყოველთვისშემდეგ ჯერზე არ მოგიწევთ არჩევანის გაკეთება. არჩევანის გადასაყენებლად გადადით აპლიკაციის თვისებებზე პარამეტრებში და იპოვეთ ღილაკი ნაგულისხმევის გასუფთავება.
აქტივობის გაშვება მისი სახელით
კონსტრუქტორში განზრახვამეორე პარამეტრი არის კლასი. მაგრამ დავუშვათ, რომ არსებობს რაიმე სახის მონაცემთა ბაზა, სადაც მითითებულია აქტივობების სახელები და ჩვენ უნდა გავუშვათ სასურველი აქტივობა მისი სახელით. ჩვენ შეგვიძლია მივიღოთ თავად კლასი string ცვლადის საფუძველზე და დავიწყოთ აქტივობა.
სცადეთ ( // აქტივობის კლასის სრული სახელი String activityName = "ru.alexanderklimov.testapplication.SecondActivity"; // მიიღეთ Class Class ობიექტი>myClass = Class.forName(activityName); Intent intent = new Intent(this, myClass); startActivity (განზრახვა); ) catch (ClassNotFoundException e) ( e.printStackTrace(); )
რატომღაც დავალება მქონდა სერვისიდან აქტივობაში გადამეტანა მონაცემები. სტანდარტულ SDK-ში გადაწყვეტის ძიება დაიწყო, მაგრამ რადგან დრო არ იყო, ცუდი გადაწყვეტილება მივიღე მონაცემთა ბაზის გამოყენების სახით. მაგრამ კითხვა ღია იყო და გარკვეული პერიოდის შემდეგ გავარკვიე უფრო სწორი გზა, რომელიც არის SDK-ში - Message, Handler, Messenger კლასების გამოყენებით.
იდეა
ჩვენ გვჭირდება მონაცემების გადატანა აქტივობიდან სერვისში და პირიქით. როგორ გავაკეთოთ ეს? ჩვენი პრობლემის მოსაგვარებლად, ჩვენ უკვე გვაქვს ყველაფერი, რაც გვჭირდება. საჭიროა მხოლოდ სერვისის მიბმა აქტივობასთან bindService-ის გამოყენებით, საჭირო პარამეტრების გავლა და პატარა ჯადოქრობა Message კლასების გამოყენების სახით. და მაგია არის Message მაგალითების ცვლადების გამოყენება და კერძოდ replyTo. ჩვენ გვჭირდება ეს ცვლადი, რათა შეგვეძლოს წვდომა Messanger-ის სერვისის მაგალითზე აქტივობიდან და სერვისში აქტივობის Messanger-ის მაგალითზე. სინამდვილეში, ეს არც ისე მარტივია. ყოველ შემთხვევაში ჩემს არცთუ ნიჭიერ გონებას. ნაწილობრივ მე უბრალოდ ვაუმჯობესებ უკვე არსებულ დოკუმენტაციას - სერვისები ასევე, არის კარგი მაგალითი StackOverflow-ზე. ნებისმიერ შემთხვევაში, იმედია სტატია ვინმეს მაინც გამოადგება და ტყუილად არ მიმუშავია.
მაგალითი
მაგალითად, ჩვენ განვახორციელებთ სერვისს, რომელიც გაზრდის და შეამცირებს მრიცხველის მნიშვნელობას და დააბრუნებს შედეგს აქტივობაში, TextView-ში. განლაგების კოდს გამოვტოვებ, რადგან არის ორი ღილაკი და ტექსტის ველი - ყველაფერი მარტივია.
განხორციელება
აქ არის სრული აქტივაციის კოდი:
საჯარო კლასის MainActivity აფართოებს აქტივობას ( საჯარო სტატიკური საბოლოო სტრიქონი TAG = "TestService"; TestServiceConnection testServConn; TextView testTxt; საბოლოო მესენჯერი მესინჯერი= new Messenger(new IncomingHandler()); Messenger toServiceMessenger; @Override public void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); testTxt = (TextView)findViewById(R.id.test_txt); bindclass. ), (testServConn = ახალი TestServiceConnection()), Context.BIND_AUTO_CREATE); ) @Override public void onDestroy()( super.onDestroy(); unbindService(testServConn); ) public void countIncrClick(View Messs)(g) მიიღეთ(null, TestService.COUNT_PLUS); msg.replyTo = მესინჯერი; სცადეთ ( toServiceMessenger.send(msg); ) დაიჭიროთ (RemoteException e) ( e.printStackTrace(); ) ) საჯარო void countDecrClick(View ღილაკი)( Message msg Message.obtain(null, TestService.COUNT_MINUS); msg.replyTo = მესინჯერი; სცადეთ ( toServiceMessenger.send(msg); ) catch (RemoteException e) ( e.printStackTrace(); ) ) კერძო კლასი IncomingHandler აფართოებს Handler-ს (@Override) void handleMessage(Message msg)( switch (msg.what) ( case TestServic e.GET_COUNT: Log.d(TAG, "(აქტივობა)...მიიღეთ რაოდენობა"); testTxt.setText(""+msg.arg1); შესვენება; ) ) ) კერძო კლასი TestServiceConnection ახორციელებს ServiceConnection ( @Override public void onServiceConnected(ComponentName name, IBinder სერვისი) ( toServiceMessenger = new Messenger(service); //send საწყისი ღირებულება counter Message msg = Message.obtain(null, TestService.SET_COUNT); msg.replyTo = მესინჯერი; msg.arg1 = 0; //ჩვენი მრიცხველი სცადეთ ( toServiceMessenger.send(msg); ) catch (RemoteException e) ( e.printStackTrace(); ) ) @Override public void onServiceDisconnected(ComponentName name) ( ) ) )
Ნება მომეცი აგიხსნა. აქტივობის შექმნისას, ჩვენ დაუყოვნებლივ ვუკავშირდებით სერვისს ServiceConnection ინტერფეისის განხორციელებით და ვუგზავნით შეტყობინებას სერვისს "დააყენეთ მასში მრიცხველის მნიშვნელობა", გადადის ნულზე და ვქმნით toServiceMessanger-ს, გადავცემთ IBinder ინტერფეისს კონსტრუქტორს. სხვათა შორის, ეს ინსტანცია უნდა დაბრუნდეს სერვისში, წინააღმდეგ შემთხვევაში იქნება NPE. ამ კლასის დახმარებით ჩვენ ვუგზავნით შეტყობინებებს სერვისს. და აი მაგია - replyTo ცვლადში ვინახავთ მესენჯერის ჩვენს სხვა ინსტანციას - ის, რომელიც პასუხს იღებს სერვერისგან და სწორედ მისი მეშვეობით განხორციელდება აქტივობასთან კომუნიკაცია.
სერვისისგან შეტყობინების მისაღებად, ჩვენ ვიყენებთ ჩვენს Handler-ს და უბრალოდ ვეძებთ ჩვენთვის საჭირო ცვლადებს და ვაკეთებთ მოქმედებებს მათზე. ღილაკზე დაწკაპუნებისას (metods countIncrClick, countDecrClick) ჩვენ ვუგზავნით მოთხოვნებს სერვისს, სადაც მითითებულია სასურველი მოქმედება msg.what ცვლადში.
პაკეტი com.example.servicetest; იმპორტი android.app.Service; იმპორტი android.content.*; იმპორტი android.os.*; android.os.Process იმპორტი; იმპორტი android.util.Log; საჯარო კლასის TestService აფართოებს სერვისს ( საჯარო სტატიკური საბოლოო int COUNT_PLUS = 1; საჯარო სტატიკური საბოლოო int COUNT_MINUS = 2; საჯარო სტატიკური საბოლოო int SET_COUNT = 0; საჯარო სტატიკური საბოლოო int GET_COUNT = 3; int count = 0; IncomingHandler inHandler; Messenger Messenger; Messenger toActivityMessenger; @Override public void onCreate()( super.onCreate(); HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); inHandlerThread. = new Messenger(inHandler); ) @Override public IBinder onBind(Intent arg0) ( return messanger.getBinder(); ) @Override public int onStartCommand(Intent intent, int flags, int startId) ( დაბრუნება START_STICKY; ) //message hand აქტივობის კერძო კლასი IncomingHandler აფართოებს Handler ( საჯარო IncomingHandler(Looper looper)( super(looper); ) @Override public void handleMessage(Message msg)( //super.handleMessage(msg); toActivityMess enger = msg.replyTo; შეცვლა (msg.what) ( case SET_COUNT: count = msg.arg1; Log.d (MainActivity.TAG, "(service)...set count"); break; case COUNT_PLUS: count++; Log.d(MainActivity.TAG , "(სერვისი)...თვლა პლუს"); შესვენება; შემთხვევა COUNT_MINUS: Log.d(MainActivity.TAG, "(სერვისი)...თვლა მინუს"); დათვლა--; შესვენება; ) //მრიცხველის გაგზავნა მნიშვნელობა Activity Message outMsg = Message.obtain(inHandler, GET_COUNT); outMsg.arg1 = დათვლა; outMsg.replyTo = მესინჯერი; სცადე ( if(toActivityMessenger != null) toActivityMessenger.send(outMsg); ) catch (RemoteException e) (e.printStackTrace(); ) ) )
ყველაფერი აქტივობაში არსებული ლოგიკის ანალოგიით. არც კი ვიცი მჭირდება თუ არა რაიმეს ახსნა. ერთადერთი საკითხია, რომ მე დაუყოვნებლივ ვუგზავნი მოთხოვნას handleMessage-ში არსებულ აქტივობაში, ამისთვის ჯადოსნური replyTo ცვლადის გამოყენებით და ზემოთ სასურველი მესენჯერის ამოღებას. და მეორე პუნქტი, რომელიც უკვე აღვნიშნე, არის:
@Override public IBinder onBind(Intent arg0) ( დაბრუნება messanger.getBinder(); )
რომლის გარეშეც ყველაფერი დაეცემა. ეს არის ინტერფეისის მაგალითი, რომელიც გადაეცემა ServiceConnection-ს
დასკვნა
Საერთო ჯამში. აქტივობასა და სერვისს შორის ურთიერთქმედების ასეთი გამოგონილი მაგალითი. მეჩვენება, რომ საკმაოდ არა ტრივიალური ურთიერთქმედებაა, თუმცა შეიძლება ვინმეს განსხვავებული ჩანდეს.
კითხვები, განმარტებები და ა.შ. შეიძლება იყოს უზუსტობები ნებისმიერ ასპექტთან დაკავშირებით, ამიტომ თავისუფლად დაწერეთ და შეასწორეთ.
ვიმედოვნებ, რომ პოსტი სასარგებლო იყო მკითხველებისთვის.
გამარჯობა.
აუცილებელია UART-ით მიღებული მონაცემების გადატანა აქტივობაში. ეს შეიძლება გაკეთდეს აქტივობაში ნაკადის შექმნით, რომელშიც მოაწყოთ გარკვეული დროის (!isInterrupted()) ციკლი და წაიკითხოთ მონაცემები UART ბუფერიდან. ამის შემდეგ, აქტივობის ინტერფეისის თემის გამოძახებით - MainActivity.this.runOnUiThread(new Runnable() , შეასრულეთ საჭირო მოქმედებები ამ აქტივობით. მაგრამ თუ ჩვენ მოვუწოდებთ სხვა აქტივობებს ძირითადი აქტივობიდან, მაშინ ორგანიზებული თემა არ იძლევა გავლის საშუალებას. მონაცემები ახლად შექმნილ აქტივობებზე. თუ სწორად მესმის, რომ ნაკადიდან მონაცემები რომ გადავიდეს რომელიმე აქტივობაზე, ნაკადი უნდა შეიქმნას არა აქტივობაში, არამედ სერვისში.
კითხვა: UART-ით შემოსული მონაცემები, იმ თემაში (რომელიც იქმნება Servce-ში) აუცილებელია მონაცემების გადატანა Activity-ზე, რომელიც ახლა აქტიურია, როგორ შეიძლება და კეთდება თუ არა საერთოდ?
1 პასუხი
თითოეულ აქტივობაში შექმენით Handler. ამ აქტივობის onResume() მეთოდში კეთდება bindService(). იქ ერთ-ერთი პარამეტრია სერვისის კავშირის ინტერფეისი. განახორციელეთ იგი მინიმუმ იგივე აქტივობით. განახორციელეთ მასში onServiceConnected() მეთოდი. ამ გამოძახებისას, თავად სერვისი მოდის, როგორც ერთ-ერთი პარამეტრი. ასე რომ, ამ სერვისს უწოდეთ თქვენი საკუთარი setHandler() მეთოდი. გადაიტანეთ Handler, რომელიც არის მიმდინარე აქტივობაში. მაგრამ გადაიტანეთ შემომავალი მონაცემები UART-ის მეშვეობით ამ დამმუშავებლის სერვისში. სხვათა შორის, Handler ტრადიციულად მუშაობს მთავარ ძაფზე, ამიტომ runOnUiThread-ის შესრულება არ დასჭირდება.