您好我正在使用Android设备作为客户端创建客户端 - 服务器应用程序。在我的应用程序中,我的客户端(android设备)发送请求,服务器对请求有响应。
我注意到导致主线程等待的任何方法都必须在不同的线程上完成。我试图这样做但在我的情况下使用ThreadExecutor
。我实现了一个帮助 Runnable
类,我传递了ObjectInputStream
但由于某种原因,它始终为null。我在这里检查了一些问题,但似乎大部分都是关于如何从一个活动转到另一个活动。但是,我想从我的activity
转到我的助手class
,我不知道该怎么做。
这是我的代码,我希望它更有意义。
package com.dozie.service;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.dcloud.common.Event;
import com.dcloud.common.Message;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class RegisterActivity extends Activity {
private Button registerButton;
private Button cancelButton;
private TextView errorText;
private EditText firstnameField, lastnameField, passwordField, cPasswordField, usernameField;
private String fname, lname, pword, cPword, uname;
private Socket socket;
private TextWatcher fnameWatcher, lnameWatcher, pwordWatcher, cPwordWatcher, unameWatcher;
protected ObjectOutputStream os;
protected ObjectInputStream is;
private ExecutorService threadPool;
private RegisterWorker worker;
public static final String PASSWORD_PATTERN = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,20})";
public static final String USERNAME_PATTERN = "^[A-z0-9_-]{5,20}$";
public static final String TAG = RegisterActivity.class.getName();
public static final int SAMEFIRSTUSER = 100; //same first name and username,
public static final int SAMELASTUSER = 200; //same last name and username
public static final int SAMEPASSFIRST = 300; //same password and firstname
public static final int SAMEPASSLAST = 400; //same password and lastname
public static final int SAMEPASSUSER = 500; //same password and username
public static final int USERNOTMATCH = 600; //username does not match
public static final int PASSNOTMATCH = 700; //password does not match
public static final int CPASS_DIFF = 800; //password and confirm password are different
public static final int GOODINPUT = 1; //every input is good
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
registerButton = (Button) findViewById(R.id.register_id);
cancelButton = (Button) findViewById(R.id.cancel_id);
firstnameField = (EditText) findViewById(R.id.firstname_id);
lastnameField = (EditText) findViewById(R.id.lastname_id);
passwordField = (EditText) findViewById(R.id.rpassword_id);
cPasswordField = (EditText) findViewById(R.id.rcpassword_id);
usernameField = (EditText) findViewById(R.id.rusername_id);
errorText = (TextView) findViewById(R.id.errorText_id);
fname="";lname="";pword="";cPword="";uname="";
//initialize TextWatchers
initializeWatchers();
// add TextWatchers
firstnameField.addTextChangedListener(fnameWatcher);
lastnameField.addTextChangedListener(lnameWatcher);
passwordField.addTextChangedListener(pwordWatcher);
cPasswordField.addTextChangedListener(cPwordWatcher);
usernameField.addTextChangedListener(unameWatcher);
cancelButton.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
firstnameField.setText("");
lastnameField.setText("");
passwordField.setText("");
cPasswordField.setText("");
usernameField.setText("");
setResult(RESULT_CANCELED);
finish();
}
});
}
@Override
public void onStart()
{
super.onStart();
Log.d(TAG, "onStart()");
Intent intent = getIntent();
final String address = intent.getStringExtra("ipAddress");
final int port = intent.getIntExtra("port", 6060);
threadPool = Executors.newFixedThreadPool(2);
new Thread(new Runnable()
{
@Override
public void run() {
// TODO Auto-generated method stub
try {
Log.i(TAG, "Trying to Connect to "+ address + " on " + port);
socket = new Socket(address, port);
Log.i(TAG, "Connection established!");
os = new ObjectOutputStream(new DataOutputStream(socket.getOutputStream()));
is = new ObjectInputStream(new DataInputStream(socket.getInputStream()));
Log.i(TAG, "Client connected to server.");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
Log.e(TAG, "UnknownHostException", e);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "I/O Exception", e);
}
}
}).start();
// threadPool.execute(worker = new RegisterWorker(is));;
}
@Override
public void onPause()
{
super.onPause();
Log.d(TAG, "onPause()");
threadPool.shutdown();
Message out = new Message("disconnect");
out.setRequest(Event.Request.DISCONNECT);
try {
os.writeObject(out);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "I/O Exception", e);
}
finally
{
try {
is.close();
os.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.i(TAG, "socket closed");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_register, menu);
return true;
}
public int validateInput(String [] input)
{
String firstname = input[0];
String lastname = input[1];
String password = input[2];
String cpassword = input[3];
String username = input[4];
Pattern pattern = Pattern.compile(PASSWORD_PATTERN);
Matcher matcher = pattern.matcher(password);
Pattern p = Pattern.compile(USERNAME_PATTERN);
Matcher m = p.matcher(username);
if(firstname.equals(username))
return RegisterActivity.SAMEFIRSTUSER;
if(lastname.equals(username))
return RegisterActivity.SAMELASTUSER;
if(firstname.equals(password))
return RegisterActivity.SAMEPASSFIRST;
if(lastname.equals(password))
return RegisterActivity.SAMEPASSLAST;
if(password.equals(username))
return RegisterActivity.SAMEPASSUSER;
if(!password.equals(cpassword))
return RegisterActivity.CPASS_DIFF;
if(!matcher.matches())
return RegisterActivity.PASSNOTMATCH;
if(!m.matches())
return RegisterActivity.USERNOTMATCH;
return RegisterActivity.GOODINPUT;
}
public void registerUser(View v)
{
String [] input = getUserInformation();
int result = validateInput(input);
switch(result)
{
case RegisterActivity.GOODINPUT:
Intent info = new Intent();
info.putExtra("username", input[4]);
registerUser(input);
if(worker.getServerResponse() != null)
{
if(worker.getServerResponse().getResponse() == Event.Response.REQUEST_SUCCESSFUL)
{
threadPool.shutdown();
setResult(RESULT_OK, info);
finish();
Log.i(TAG, "registerUser(): data input successful!");
}
else if(worker.getServerResponse().getResponse() == Event.Response.REQUEST_UNSUCCESSFUL)
{
threadPool.execute(worker);
Log.i(TAG, "registerUser(): data input unsuccessful!");
}
}
break;
case RegisterActivity.SAMEFIRSTUSER:
errorText.setText("username should not be the same as firstname");
Log.i(TAG, "registerUser(): username same as firstname");break;
case RegisterActivity.SAMELASTUSER:
errorText.setText("username should not be the same as lastname");
Log.i(TAG, "registerUser(): username same as lastname");break;
case RegisterActivity.SAMEPASSFIRST:
errorText.setText("password should not be the same as firstname");
Log.i(TAG, "registerUser(): password same as firstname");break;
case RegisterActivity.SAMEPASSLAST:
errorText.setText("password should not be the same as lastname");
Log.i(TAG, "registerUser(): password same as lastname");break;
case RegisterActivity.SAMEPASSUSER:
errorText.setText("password should not be the same as username");
Log.i(TAG, "registerUser(): password same as username");break;
case RegisterActivity.CPASS_DIFF:
errorText.setText("password and confirm password are not the same");
Log.i(TAG, "registerUser(): password and confirm password not the same");break;
case RegisterActivity.PASSNOTMATCH:
errorText.setText("password format wrong. Password should contain 6-20 characters\n" +
"characters containing at least 1 digit, 1 lower case alphabet and 1 upper case character");
Log.i(TAG, "registerUser(): password format not correct");break;
case RegisterActivity.USERNOTMATCH:
errorText.setText("username format wrong. username should contain 5-20 characters " +
"and should have to special characters");
Log.i(TAG, "registerUser(): username format not correct");break;
default:
Log.i(TAG, "registerUser(): Code not handled");break;
}
}
public String [] getUserInformation()
{
String firstname = firstnameField.getText().toString();
String lastname = lastnameField.getText().toString();
String password = passwordField.getText().toString();
String cpassword = cPasswordField.getText().toString();
String username = usernameField.getText().toString();
String [] input = {firstname, lastname, password, cpassword, username};
return input;
}
public void initializeWatchers()
{
fnameWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
fname = firstnameField.getText().toString();
fname.trim();
updateButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
};
lnameWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
lname = lastnameField.getText().toString();
lname.trim();
updateButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
};
pwordWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
pword = passwordField.getText().toString();
pword.trim();
updateButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
};
cPwordWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
cPword = cPasswordField.getText().toString();
cPword.trim();
updateButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
};
unameWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
uname = usernameField.getText().toString();
uname.trim();
updateButton();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
};
}
public void updateButton()
{
boolean enabled = fname.length()>0 && lname.length()>0 && pword.length()>0
&& cPword.length()>0 && uname.length() >0;
registerButton.setEnabled(enabled);
}
public void registerUser(String [] input)
{
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("Register");
doc.appendChild(rootElement);
Element user = doc.createElement("user");
rootElement.appendChild(user);
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode(input[0]));
user.appendChild(firstname);
Element lastname = doc.createElement("lastname");
lastname.appendChild(doc.createTextNode(input[1]));
user.appendChild(lastname);
Element password = doc.createElement("password");
password.appendChild(doc.createTextNode(input[2]));
user.appendChild(password);
Element username = doc.createElement("username");
username.appendChild(doc.createTextNode(input[4]));
user.appendChild(username);
StringWriter writer = new StringWriter();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(writer));
String content = writer.toString();
Message out = new Message(content);
out.setRequest(Event.Request.REGISTER);
os.writeObject(out);
Log.d(TAG, "registerUser(): Register message sent");
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
Log.e(TAG, "onActivityReturn(): ParserConfigurationException error", e);
} catch (TransformerException e) {
// TODO Auto-generated catch block
Log.e(TAG, "onActivityReturn(): TransformerException error", e);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e(TAG, "onActivityReturn(): IOException error", e);
}
}
}
<p>And for my runnable class</p>
package com.dozie.service;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OptionalDataException;
import android.util.Log;
import com.dcloud.common.Event;
import com.dcloud.common.Message;
public class RegisterWorker implements Runnable{
private ObjectInputStream is;
private Message in;
public static final String TAG = RegisterWorker.class.getName();
public RegisterWorker(ObjectInputStream is)
{
this.is = is;
if(this.is == null)
System.out.println("null");
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while((in = (Message) is.readObject())!=null)
{
if(in.getResponse() == Event.Response.REQUEST_SUCCESSFUL)
{
Log.d(TAG, "Login Response: "+in.getMessage());
}
else if(in.getResponse() == Event.Response.REQUEST_UNSUCCESSFUL)
{
Log.d(TAG, "Login Response: "+in.getMessage());
//give reason for rejection
}
}
} catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Message getServerResponse()
{
return in;
}
}
答案 0 :(得分:1)
简单的方法是创建一个静态变量并为其赋值。 其他解决方案是创建一个对象,其中包含要在runnable和activity之间传递的值列表,并在创建实例时传递此对象
在您的情况下,它可能看起来像MyObject myObject = null;
public RegisterWorker(ObjectInputStream is, MyObject myObject)
{
this.is = is;
this.myObject=myObject;
if(this.is == null)
System.out.println("null");
}
当处理完成后,您可以添加一个方法来返回对象 所以你的活动类可以调用该方法并将其用于进一步处理。
public MyObject getMyObject(){
retunr myObject
}
但是你可以尝试的另一种方法是使用AsyncTask。在哪里可以提到在创建AsyncTask时要返回的内容。
答案 1 :(得分:1)
我认为你写的代码比它需要的更复杂。如果你想将变量传递给Thread
,这是我认为你想要做的,只需这样做:
public Worker extends AsyncTask<Arguments, Void, Void> {
// method names may be slightly incorrect, writing this from memory
public void runInBackground(Arguments...args) {
// do what you want to do in the background
}
}
然后开始你的主题:
Arguments args = new Arguments(arg1, arg2); // whatever you want to pass along
new Worker().execute(args);
Arguments
可以是任何类,以此为例。
希望这有帮助。