当前位置: 首页 > 知识库问答 >
问题:

在完成无泄漏时终止来自AsyncTask的网络服务发现

孟永望
2023-03-14

我正在尝试简单地找到一个带有MDN的设备,保存IP并杀死“网络服务发现”(NSD)一旦完成。

NSD和AsyncTask在这里冲突。

使用NSD获取IP是可行的,但如果AsyncTask不是静态的,它会警告泄漏。

如果AsyncTask是静态的,则NSD从onPostExecute()表示;
非静态字段'mNSDManager'不能从静态上下文引用

如果我将AsyncTask设置为静态但必须注释掉MNSDManager.StopServiceDiscovery(mDiscoveryListener),则如果应用程序退出,NSD仍然会从onDestroy中被杀死;在onPostExecute()中执行此操作。

使用NSD,我可以在5-15秒内获得IP,但如果AsyncTask是静态的,我不能杀死它,NSD就会非常忙。

如果我通过使AsyncTask静态化来满足它,mNsdManager会抱怨:
非静态字段'mNsdManager'不能从静态上下文引用

我可以编译的唯一方法是使AsyncTask非静态,接受可能的泄漏,或者保留AsyncTask静态,并注释掉onPostExecute()中的KILL行。

下面的代码中标记了2个错误。

基于Android事件的AsyncTask似乎是最好的方法,但这是正确的方法吗?

我怎样才能杀死mNsdManager而仍然使AsyncTask保持静态以阻止泄漏?


    package com.fib.onacci.fibonacci;

    private static final String TAG = "CLOCK : ";
    private TextView mIP_address;

    // NSD members, Allows app to discover the "fibonacci.local"
    // Reference: 
    // http://developer.android.com/training/connect-devices-wirelessly/nsd.html

          private static NsdManager mNsdManager;
          private static NsdManager.DiscoveryListener mDiscoveryListener;
          private NsdManager.ResolveListener mResolveListener;
          private NsdServiceInfo mServiceInfo;
          public String mRPiAddress;
          public static String IPaddress ="-"; // something to look for change
          private static final String SERVICE_TYPE = "_http._tcp."; 

        public class MainActivity extends AppCompatActivity {

        private static final String TAG = "CLOCK: ";

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);

              new getIPtoTextView().execute();  // start the AsyncTask

              // setup nDNS and find IP
              mRPiAddress = "";
              IPaddress = "-";
              mNsdManager = (NsdManager)(getApplicationContext().getSystemService(Context.NSD_SERVICE));
              initializeResolveListener();
              initializeDiscoveryListener();
              mNsdManager.discoverServices( SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);

          }  // END onCreate

         // NSD start - Network discovery

ERROR This AsyncTask class should be static or leaks might occur 
          A static field will leak contexts.   

          private static class getIPtoTextView extends AsyncTask {
              /** part of nDiscovery - find clock and kill discovery service
               *  `doInBackground` is run on a separate, background thread
               */
              @Override
              protected Void doInBackground(Void... params) {
                  String mloop = IPaddress;
                  while ( mloop.equals("-")) {
                      mloop = IPaddress;
                      try {
                          Thread.sleep(100);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  Log.i( TAG, "doInBackground - IP Found - " + mloop );
                  return null;
              }

              /** part of nDiscovery
               * `onPostExecute` is run after `doInBackground`, and it's
               * run on the main/ui thread, so you it's safe to update ui
               * components from it. (this is the correct way to update ui
               * components.)
               */
              @Override
              protected void onPostExecute(Void param) {
                Log.i( TAG, "onPostExecute - IP Found - " + IPaddress );

                  TextView IP_Window = findViewById(R.id.IP_address); 
                  IP_Window.setText( IPaddress);  // post IP address to TextView

ERROR Non-static field 'mNsdManager' cannot be referenced from a static context
                  mNsdManager.stopServiceDiscovery( mDiscoveryListener);                     // kill mDiscoveryListener
              }
          }  // end asyncTask class

          private void initializeDiscoveryListener() {

            mDiscoveryListener = new NsdManager.DiscoveryListener() { // Listener

                  @Override
                  public void onDiscoveryStarted(String regType) {
                  }

                  @Override
                  public void onServiceFound(NsdServiceInfo service) { // service found!
                      String name = service.getServiceName();
                      String type = service.getServiceType();

                      if ( type.equals(SERVICE_TYPE) && name.contains("Fibonacci")) {
                          Log.i( TAG, "\n\tNSD Service Found @ ' " + name + "'");
                          mNsdManager.resolveService(service, mResolveListener);
                      }
                  }

                  @Override
                  public void onServiceLost(NsdServiceInfo service) {  
                  }

                  @Override
                  public void onDiscoveryStopped(String serviceType) {
                  }

                  @Override
                  public void onStartDiscoveryFailed(String serviceType, int errorCode) {
                      mNsdManager.stopServiceDiscovery(this);
                  }

                  @Override
                  public void onStopDiscoveryFailed(String serviceType, int errorCode) {
                      mNsdManager.stopServiceDiscovery(this);
                  }
              };
          }

          private void initializeResolveListener() {
              mResolveListener = new NsdManager.ResolveListener(){

                  @Override
                  public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                      Log.i( TAG, "\n\t\tNSD Resolve failed " + errorCode + "\n\n" );
                  }

                  @Override
                  public void onServiceResolved( NsdServiceInfo serviceInfo ) {
                      mServiceInfo = serviceInfo;
                      InetAddress host = mServiceInfo.getHost();
                       IPaddress = host.getHostAddress();
                      mRPiAddress = IPaddress;
                      Log.i( TAG, "\n\t\tNSD Resolved address = " + IPaddress + "\n\n" );
                    }
                };
            }

            @Override
            protected void onPause() {
                super.onPause();
                if ( mDiscoveryListener != null) {
                    mNsdManager.stopServiceDiscovery( mDiscoveryListener);
                }
            }

            @Override
            protected void onResume() {
                super.onResume();
                if ( mDiscoveryListener != null) {
                  mIP_address.setText( R.string.searching );  // TextView - Searching -
                    try {
                        Thread.sleep( 1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    initializeDiscoveryListener();
                }
            }

            @Override
            protected void onDestroy() {
                super.onDestroy();
                mNsdManager.stopServiceDiscovery( mDiscoveryListener);  
            }
        // NSD end //
      }

共有1个答案

尹欣怿
2023-03-14

需要重写,因为我无法在没有太多错误的情况下使类getIPtoTextView成为静态的。

一旦我可以将类getIPtoTextView设置为静态,我就移动了MNSDManager.StopServiceDiscovery(mDiscoveryListener);onPause()和onDestroy()都工作得很好。

 类似资料:
  • 问题内容: 我有一个正在从给定的计时器开始执行后台任务的方法。我需要短暂的网络任务,所以这就是我坚持的原因。 从,我正在执行需要执行的许多操作(例如启动通知)。现在,在初始化时,我得到一条警告:“ 此字段泄漏了上下文对象。 ” 我看到了许多关于相同的问题,但是它们都与之有关。所以我的问题是,如何在我的(顶级课程)中 使用它而不泄漏它 ? 问题答案: 我有一个服务,可以从该服务从给定的计时器启动As

  • 我的模板如下所示 现在,当我试图在注释字段“今天的天气预报是”中使用以下字符串构建模板时,velocity最终将其呈现为 我如何防止它逃脱我的角色?

  • 各位,我使用插件cargo-maven2-plugin在Tomcat8上运行集成测试(等待tomcat8-maven-plugin) 不幸的是,当我停止容器时,我有这样一个堆栈:

  • 本文向大家介绍Android 避免使用AsyncTask泄漏活动,包括了Android 避免使用AsyncTask泄漏活动的使用技巧和注意事项,需要的朋友参考一下 示例 注意:AsyncTask除了这里描述的内存泄漏之外,还有很多陷阱。因此,请谨慎使用此API,如果您不完全了解其含义,请完全避免使用它。有很多选择(线程,EventBus,RxAndroid等)。 一个常见的错误AsyncTask是

  • 问题内容: 我有一个行为异常的应用程序,似乎在泄漏。经过简要的探查器调查后,大多数内存(80%)由实例保留。我怀疑终结器无法运行。 造成这种情况的常见原因似乎是终结器抛出异常。但是,该类方法的javadoc (例如参见此处)似乎自相矛盾:它指出 如果finalize方法抛出未捕获的异常,则该异常将被忽略,并且该对象的终止将终止。 但后来,它也指出 由finalize方法引发的任何异常都会导致该对象

  • 我的遗嘱执行人服务是这样的: 实现了runnable,它的run方法具有巨大的功能,需要调用其他几个API。现在,当我在调试模式下运行代码时,任务就完成了。当我正常运行时,任务是不完整的,线程被终止。线程不是要等到所有任务都完成了吗?为什么他们没有完成任务就被解雇了?