意识到我必须担心基于网络的线程会对我的 UI 线程造成严重破坏,我经历了为我的应用程序和远程服务器之间的命令和响应的 TCP/IP 网络乒乓球创建自定义处理程序和自定义线程的整个过程。效果很好。(您将在下面的代码中看到它被引用为mainCommunicationThread(controlCommands);)
在触发该线程/处理程序之前,我从 SQL 中提取 IP 或主机名(称为 currIPstr),然后将其与一堆其他变量一起发送到线程/处理程序。不过,我需要做的一件事是确保它是 A) 有效的 IP 地址,或者 B) 主机名已解析 - 否则,甚至开始尝试都没有意义。
好吧,没问题,我只是这样称呼:
currIP = InetAddress.getByName(currIPstr).toString().split("/")[1];
Run Code Online (Sandbox Code Playgroud)
不过,我刚刚遇到的情况是,当 Gingerbread 或 StrictMode 运行时,上面的行会触发可怕的 NetworkOnMainThreadException。
是的,对 InetAddress.getByName 的简单调用就足够了。好吧,我一直在努力解决问题,所以我将整个函数移到了可运行的环境中:
private String currStatIP = null;
private String currentStatIPstr = null;
private Integer currentStatIDstr = -1;
private String currentPort = null;
private String currentLocation = null;
private String currUserName = null;
private String currPassword = null;
private Integer currStatID = -1;
public void StatControl(Cursor c, final String[] commandtosend){
/*the object will always start off with the first 4 fields being the current login information.
* [0] = IP Address
* [1] = port number
* [2] = username
* [3] = password
* [4] = COMMAND -- this will be used in a switchcase inside the pingpong to decide what to do.
* -- if the Socket is not open, the first 4 fields will be used to re-initiate the connection
* -- otherwise, the command is drawn from this field and sent directly.
* */
currentStatIDstr = c.getInt(0);
currentStatIPstr = c.getString(1);
currentPort = c.getString(2);
currentLocation = c.getString(3);
currUserName = c.getString(4);
currPassword = c.getString(5);
currStatID = currentStatIDstr;
Handler networkLookupHandler = new Handler();
Runnable networkLookupRunnable = new Runnable() {
public void run() {
try {
currStatIP = InetAddress.getByName(currentStatIPstr).toString().split("/")[1];
} catch (UnknownHostException e) {
e.printStackTrace();
}
int portNumber = 0;
try {
portNumber = Integer.parseInt(currentPort);
} catch(NumberFormatException nfe) {
nfe.printStackTrace();
}
String userName = currUserName;
String passWord = currPassword;
String[] command = commandtosend;
Object[] controlCommands = new Object[]{
currStatID,
currStatIP, //InetAddress of String representing the IP address
portNumber, //int representation of the port number, taken from String
currentLocation,
userName,
passWord,
command
};
/*for(int i=0;i<controlCommands.length;i++){
Log.d("object work","controlCommands[" + i + "] is " + controlCommands[i]);
}*/
mainCommunicationThread(controlCommands);
}
};
networkLookupHandler.post(networkLookupRunnable);
}
Run Code Online (Sandbox Code Playgroud)
而且,耶!有效!我不再收到 NetworkOnMainThreadException 了。哦...等等..是的,我是。
上述内容不会在 API 10、12、14 上触发异常,甚至 16 在模拟器中也能正常工作,但是,如果我将其加载到运行 Jellybean 4.1.1 的 Samsung Google Galaxy Nexus 上,则会出现 NetworkOnMainThreadException 崩溃。即使上面的内容包裹在可运行的内部。
我完全不知道如何解决这个问题。
您正在尝试在可运行的网络操作中运行,因此请尝试在 onCreate 方法中添加以下代码:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Run Code Online (Sandbox Code Playgroud)
或者我建议您使用 asynctask 而不是使用 Runnable 线程
小智 5
我的解决方案:
public static InetAddress getInetAddressByName(String name)
{
AsyncTask<String, Void, InetAddress> task = new AsyncTask<String, Void, InetAddress>()
{
@Override
protected InetAddress doInBackground(String... params)
{
try
{
return InetAddress.getByName(params[0]);
}
catch (UnknownHostException e)
{
return null;
}
}
};
try
{
return task.execute(name).get();
}
catch (InterruptedException e)
{
return null;
}
catch (ExecutionException e)
{
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5678 次 |
| 最近记录: |