One of the tutorials on Android Application Development provides a logon dialog box.
Difficulty:
Suitable for: Android Developers
Brief description: for network applications, the "logon box" is quite common. There are no complicated items in the Code. It is basically a uidesign. It is suitable for practitioners and can be downloaded after the code is logged on.
Requirement Analysis:
1. Enter the user name and password
2. Extract user name and password information
3. Progress bar during logon
4. Timeout Processing
5. logon successful jump
6. (not all of them are listed. Please add them as needed)
Step 1:
Objective: To design the UI
1.1 compile layout XML login_view.xml
Tablelayout is a natural fit for the four-way regular layout. It is worth noting that each row is identified by a tablerow label. It's too ugly to post code on the Forum, so I only paste the key. After the complete code tutorial is completed, download is provided.
<Tablerow> <br/> <textview Android: text = "@ string/username" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content"/> <br/> <edittext Android: layout_width = "fill_parent" <br/> Android: layout_height = "wrap_content" <br/> Android: layout_weight = "1.0" type = "regxph" text = "yourobjectname"/> <br/> tablerow>
The layout_weight attribute is added to extend edittext to the rightmost.
<Linearlayout> <br/> <button Android: text = "@ string/login" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: layout_weight = "1.0"/> <br/> <button Android: text = "@ string/cancel" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: layout_weight = "1.0"/> <br/> linearlayout>
Here, the layout_weight attribute is used to ensure that the two buttons have equal width and can be filled with a line. Because 1.0: 1.0 =. The width is equal.
See the following results in Eclipse:
1.2 write a class to test it
Both diyout and activity can load this layout.
Testloginview. java <br/> package Org. androidin. tutorial; <br/> Import android. app. activity; <br/> Import android. app. dialog; <br/> Import android. content. intent; <br/> Import android. OS. bundle; <br/> Import android. view. view; <br/> Import android. view. view. onclicklistener; <br/> Import android. widget. button; <br/> public class testloginview extends activity {<br/>/** called when the activity is first created. */<br/> Public static button btnactivity; <br/> Public static button btndialog; <br/> Public void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); <br/> setcontentview (R. layout. main); <br/> btnactivity = (button) findviewbyid (R. id. test_activity); <br/> btnactivity. setonclicklistener (New btnactivityoncliklistener (); <br/> btndialog = (button) findviewbyid (R. id. test_dialog); <br/> btndialog. setonclicklistener (New btndialogonclicklistener (); <br/>}< br/> private class btndialogonclicklistener implements onclicklistener {<br/> Public void onclick (view V) {<br/> dialog = new dialog (testloginview. this); <br/> dialog. setcontentview (R. layout. login_view); <br/> dialog. settitle (getstring (R. string. address); <br/> dialog. show (); <br/>}< br/> private class btnactivityoncliklistener implements onclicklistener {<br/> Public void onclick (view V) {<br/> intent = new intent (); <br/> intent. setclass (testloginview. this, loginviewonactivity. class); <br/> startactivity (intent); <br/>}</P> <p> loginviewonactivity. java <br/> package Org. androidin. tutorial; <br/> Import android. app. activity; <br/> Import android. OS. bundle; <br/> public class loginviewonactivity extends activity {<br/> Public void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); <br/> settitle (getstring (R. string. address); <br/> setcontentview (R. layout. login_view); <br/>}< br/>}
Step 2:
Add the progress UI to the target and design the login control architecture (LOGIN logic, failed or successfully handled ).
First, add progress. By default, progress is invisible. Therefore, set "gone" on the property of Android: visibility. This parameter will make the control not displayed and not placeholder, for more information, see the official documentation.
Android: visibility = "gone"> <br/> <rogressbar Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: textsize = "17.5sp" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "fill_parent" <br/> Android: gravity = "center" <br/>
The next step is the key part. The login logic of each application is different, so write an Interface
Public interface onloginlistener {<br/> Public Boolean onlogin (view V, string username, string password); <br/> // view V is the view that calls this method, their parameters are not mentioned. <br/> Public void onloginsuccess (view V); <br/> Public void onloginfailed (view V); <br/>}
Next we need to encapsulate the entire loginview, because we need to add the view in XML to loginview, So we inherit the framelayout
Public class loginview extends framelayout {<br/> protected button btnlogin; <br/> protected button btncancel; <br/> protected edittext edtusername; <br/> protected edittext edtpassword; <br/> protected view progress; <br/> private onloginlistener; <br/> loginview (context ); // initialize the attribute <br/> Public void setonloginlistener (onloginlistener L); // set the logon logic listener <br/> Public void setcancelonclicklistener (onclicklistener L ); // set the listening of the cancel button <br/> Public void setloginonclicklistener (onclicklistener L); // set the listening of the login button <br/>}
Next we will implement the method one by one.
Only one constructor method is reloaded here. In fact, multiple constructor methods may need to be reloaded. Therefore, write a function to initialize the view separately.
Private void initviews () {<br/> inflate (getcontext (), R. layout. login_view, this); <br/> btnlogin = (button) findviewbyid (R. id. login_view_login); <br/> btncancel = (button) findviewbyid (R. id. login_view_cancel); <br/> edtusername = (edittext) findviewbyid (R. id. login_view_username); <br/> edtpassword = (edittext) findviewbyid (R. id. login_view_password); <br/> btnlogin. setonclicklistener (New loginbuttonlistene R (); // The default listening process logic is described below. <Br/> progress = findviewbyid (R. id. login_view_progress); <br/>}< br/> Public loginview (context) {<br/> super (context); <br/> initviews (); <br/>}< br/> Public void setonloginlistener (onloginlistener L) {<br/> onloginlistener = L; <br/>}< br/> Public void setcancelonclicklistener (onclicklistener L) {<br/> btncancel. setonclicklistener (l); <br/>}< br/> Public void setloginonclicklistener (onclicklistener L) {<br/> btnlogin. setonclicklistener (l); <br/>}
Let's look back at the default processing logic added above.
Private class loginbuttonlistener implements onclicklistener
For general applications, you must connect to the local database remotely through socket. Reading local data is fine, but it may take some time to use socket communication. In the event of network congestion, the login process is even longer. Second, socket is a blocking method, that is, if the connection is not applied, the thread that calls the socket is also in the waiting state. The program will not run.
So the solution is to create a thread to handle the login process.
Private class loginbuttonlistener implements onclicklistener {<br/> Public void onclick (view v) {<br/> If (onloginlistener! = NULL) {<br/> loginthread = new loginthread (); <br/> loginthread. start (); <br/>}</P> <p> protected class loginthread extends thread {<br/> Public void run () {<br/> handler. sendemptymessage (set_onlogin_true); // you can specify whether the control is unavailable. <br/> Boolean flag = onloginlistener. onlogin (<br/> loginview. this, <br/> edtusername. gettext (). tostring (), <br/> edtpassword. gettext (). tostring (); </P> <p> If (FLAG) <br/> onloginlistener. onloginsuccess (loginview. this); <br/> else <br/> onloginlistener. onloginfailed (loginview. this); <br/> handler. sendemptymessage (set_onlogin_false); // sets whether the control is available <br/>}< br/> };
The handler here is used to change the control attributes in a non-main program thread. Android requires that the control attributes cannot be changed in other non-main threads. However, handler can be used to handle similar situations. For more information, see the official documentation.
This is the basic framework. Next we will explain how to use this loginview.
Of course, you must first implement an onloginlistener
Package Org. androidin. tutorial. view; </P> <p> Import Org. androidin. tutorial. loginsuccessactivity; <br/> Import Org. androidin. tutorial. r; </P> <p> Import android. content. context; <br/> Import android. content. intent; <br/> Import android. OS. handler; <br/> Import android. view. view; <br/> Import android. widget. toast; </P> <p> public class onloginlistenerimpl implements onloginlistener {<br/> protected object session; // It is used to save the return values of some logon statuses, which can be hashmap. You can use it based on your actual application. <br/> protected handler; // all these methods are called in another thread, so handler is used to change the attributes of some controls. <Br/> Public onloginlistenerimpl (handler) {<br/> This. handler = handler; <br/>}</P> <p> Public Boolean onlogin (view V, string username, string password) {<br/> for (INT I = 0; I <10000000; I ++) // This method simulates blocked sockets <br/>; <br/> If (username. equals ("androidin") return true; // logon successful <br/> return false; // Logon Failed <br/>}</P> <p> Public void onloginfailed (final view v) {<br/> handler. post (New runnable () {// a toast <br/> Public void run () {<br/> toast. maketext (<br/> v. getcontext (), <br/> v. getcontext (). gettext (R. string. login_failed), <br/> toast. length_long ). show (); <br/>}< br/>}); <br/>}</P> <p> Public void onloginsuccess (view V) {<br/> context = v. getcontext (); <br/> context. startactivity (new intent (context, <br/> loginsuccessactivity. class); // jump to the success page <br/>}< br/>}
Let's assemble it now. This example shows the control in activity.
Package Org. androidin. tutorial; </P> <p> Import Org. androidin. tutorial. view. loginview; <br/> Import Org. androidin. tutorial. view. onloginlistenerimpl; </P> <p> Import android. app. activity; <br/> Import android. OS. bundle; <br/> Import android. OS. handler; <br/> Import android. view. view; <br/> Import android. view. view. onclicklistener; </P> <p> public class loginviewonactivity extends activity {<br/> private loginview logv; </P> <p> Public void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); <br/> settitle (getstring (R. string. address); <br/> logv = new loginview (this); <br/> logv. setonloginlistener (New onloginlistenerimpl (new handler (); <br/> logv. setcancelonclicklistener (New onclicklistener () {<br/> Public void onclick (view v) {<br/> finish (); <br/>}< br/> }); <br/> setcontentview (logv); <br/>}< br/>}
So, easy !!
There is also a small bug. I don't know if you have found it. The bug fix remains in step 3.
Step 3:
Objective: To fix bugs and add timeout Processing
There is a small bug left in step 2. When you click the login button, if you force terminate (for example, press the back key) before the logon status returns ). The login logic cannot be terminated because the login logic is in a new thread. Therefore, you must be able to terminate the login logic thread. To terminate a thread, you can call thread. Stop () thread. Interrupt (). The stop method is not safe and may cause deadlocks. Interrupt only changes the thread state, rather than terminating the thread in real time.
Therefore, we set an islogincanceled to verify the status after the logon status is returned. If it is canceled, the following program will not be implemented.
Protected class loginthread extends thread {<br/> Public void run () {<br/> handler. sendemptymessage (set_onlogin_true); <br/> Boolean flag = onloginlistener. onlogin (loginview. this, edtusername <br/>. gettext (). tostring (), edtpassword. gettext (). tostring (); <br/> If (islogincanceled) {<br/> return; <br/>}< br/> If (FLAG) <br/> handler. sendemptymessage (login_success); <br/> else <br/> handler. sendemptymessage (login_failed); <br/> handler. sendemptymessage (set_onlogin_false); <br/>}< br/> };
We adopt a similar method for timeout processing. After timeout, assign islogincanceled to true. The following logic will not be executed.
Private class loginbuttonlistener implements onclicklistener {<br/> Public void onclick (view v) {<br/> If (onloginlistener! = NULL) {<br/> islogincanceled = false; <br/> If (timeout! = 0) <br/> handler. sendemptymessagedelayed (login_timeout, timeout); <br/> loginthread = new loginthread (); <br/> loginthread. start (); <br/>}< br/> private handler = new handler () {<br/> @ override <br/> Public void handlemessage (Message MSG) {<br/> switch (MSG. what) {<br/> case set_onlogin_true: <br/> setonloging (true); <br/> break; <br/> case set_onlogin_false: <br/> setonloging (false); <br/> break; <br/> case login_timeout: <br/> onloginlistener. onlogintimeout (loginview. this); <br/> logincancel (); <br/> sendemptymessage (set_onlogin_false); <br/> break; <br/> case login_success: <br/> onloginlistener. onloginsuccess (loginview. this); <br/> break; <br/> case login_failed: <br/> onloginlistener. onloginfailed (loginview. this); <br/> break; <br/>}< br/> super. handlemessage (MSG); <br/>}< br/> };
From: http://www.aidiji.com/viewtopic.php? F = 27 & t = 394 & START = 0
Because I did not find the ready-made source code in my post, I will try this method later and release the method as feasible!