我试图简单地找到一个带有 mDNS 的设备,保存 IP 并在完成后终止“网络服务发现”(NSD)。
NSD 和 AsyncTask 在这里发生冲突。
使用 NSD 获取 IP 是可行的,但如果 AsyncTask 不是静态的,它会警告泄漏。
如果 AsyncTask 是静态的,NSD 说 from onPostExecute();
不能从静态上下文中引用非静态字段“mNsdManager”
如果我将 AsyncTask 设为静态但必须注释掉mNsdManager.stopServiceDiscovery(mDiscoveryListener); 在 onPostExecute() 中执行此操作。
使用NSD,我可以在 5-15 秒内获得 IP,但是如果 AsyncTask 是静态的,如果我无法杀死它,NSD 会保持非常忙碌。
如果我通过使其成为静态mNsdManager来满足 AsyncTask 的抱怨:
无法从静态上下文中引用非静态字段“mNsdManager”
我可以编译的唯一方法是使 AsyncTask 非静态并接受可能的泄漏- 或 -将 AsyncTask 保留为静态并注释掉 onPostExecute() 中的 KILL 行。
下面的代码中标记了 2 个错误。
使用基于 Android 事件的 AsyncTask 似乎是最好的方法,但它是正确的方法吗?
我怎样才能杀死mNsdManager并仍然使AsyncTask静态以阻止泄漏?
包 com.fib.onacci.fibonacci; 私人静态最终字符串标签=“时钟:”; 私有 TextView mIP_address; // NSD 成员,允许应用发现“fibonacci.local” // 参考: // http://developer.android.com/training/connect-devices-wireless/nsd.html 私有静态 NsdManager mNsdManager; 私有静态 NsdManager.DiscoveryListener mDiscoveryListener; 私有 NsdManager.ResolveListener mResolveListener; 私有 NsdServiceInfo mServiceInfo; 公共字符串 mRPiAddress; 公共静态字符串IP地址="-"; // 寻找改变的东西 private static final String SERVICE_TYPE = "_http._tcp."; 公共类 MainActivity 扩展 AppCompatActivity { 私人静态最终字符串标签=“时钟:”; @覆盖 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); 新的 getIPtoTextView().execute(); // 启动异步任务 // 设置 nDNS 并查找 IP mRPiAddress = ""; IP地址=“-”; mNsdManager = (NsdManager)(getApplicationContext().getSystemService(Context.NSD_SERVICE)); 初始化解析监听器(); 初始化发现监听器(); mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); } // 结束 onCreate // NSD 启动 - 网络发现 错误此 AsyncTask 类应该是静态的,否则可能会发生泄漏 静态字段会泄漏上下文。 私有静态类 getIPtoTextView 扩展 AsyncTask { /** nDiscovery 的一部分 - 查找时钟并终止发现服务 * `doInBackground` 在单独的后台线程上运行 */ @覆盖 受保护的无效doInBackground(无效...参数){ 字符串 mloop = IP 地址; while ( mloop.equals("-")) { mloop = IP地址; 尝试 { 线程.sleep(100); } 捕捉(InterruptedException e){ e.printStackTrace(); } } Log.i( TAG, "doInBackground - IP Found - " + mloop ); 返回空值; } /** nDiscovery 的一部分 * `onPostExecute` 在 `doInBackground` 之后运行,它是 * 在 main/ui 线程上运行,所以你可以安全地更新 ui *它的组件。(这是更新ui的正确方法 * 成分。) */ @覆盖 受保护的无效onPostExecute(无效参数){ Log.i( TAG, "onPostExecute - IP Found - " + IPaddress ); TextView IP_Window = findViewById(R.id.IP_address); IP_Window.setText(IP地址); // 将 IP 地址发布到 TextView 错误不能从静态上下文引用非静态字段“mNsdManager” mNsdManager.stopServiceDiscovery(mDiscoveryListener); // 杀死 mDiscoveryListener } } // 结束 asyncTask 类 私人无效初始化发现侦听器(){ mDiscoveryListener = new NsdManager.DiscoveryListener() { // 监听器 @覆盖 公共无效 onDiscoveryStarted(字符串 regType){ } @覆盖 public void onServiceFound(NsdServiceInfo service) { // 找到服务! 字符串名称 = service.getServiceName(); 字符串类型 = service.getServiceType(); if ( type.equals(SERVICE_TYPE) && name.contains("Fibonacci")) { Log.i( TAG, "\n\tNSD 服务找到@'" + 名称 + "'"); mNsdManager.resolveService(service, mResolveListener); } } @覆盖 公共无效 onServiceLost(NsdServiceInfo 服务){ } @覆盖 公共无效 onDiscoveryStopped(字符串服务类型){ } @覆盖 公共无效 onStartDiscoveryFailed(字符串 serviceType,int errorCode){ mNsdManager.stopServiceDiscovery(this); } @覆盖 公共无效 onStopDiscoveryFailed(String serviceType, int errorCode) { mNsdManager.stopServiceDiscovery(this); } }; } 私人无效initializeResolveListener(){ mResolveListener = new NsdManager.ResolveListener(){ @覆盖 公共无效onResolveFailed(NsdServiceInfo serviceInfo,int errorCode){ Log.i( TAG, "\n\t\tNSD 解析失败 " + errorCode + "\n\n" ); } @覆盖 公共无效onServiceResolved(NsdServiceInfo serviceInfo){ mServiceInfo = 服务信息; InetAddress 主机 = mServiceInfo.getHost(); IPaddress = host.getHostAddress(); mRPiAddress = IP 地址; Log.i( TAG, "\n\t\tNSD 解析地址 = " + IPaddress + "\n\n" ); } }; } @覆盖 受保护的无效 onPause() { 超级.onPause(); if ( mDiscoveryListener != null) { mNsdManager.stopServiceDiscovery(mDiscoveryListener); } } @覆盖 受保护的无效 onResume() { 超级.onResume(); if ( mDiscoveryListener != null) { mIP_address.setText(R.string.searching); // TextView - 搜索 - 尝试 { 线程.sleep(1500); } 捕捉(InterruptedException e){ e.printStackTrace(); } 初始化发现监听器(); } } @覆盖 受保护的无效 onDestroy() { super.onDestroy(); mNsdManager.stopServiceDiscovery(mDiscoveryListener); } // NSD结束 // }