DesignMode с вложенными Средствами управления

Этот ответ может быть запоздалым, но я хотел бы упомянуть несколько вещей, когда ваш Activity зависит от AsyncTask. Это поможет вам предотвратить сбои и управление памятью. Как уже упоминалось в приведенных выше ответах, переходите к interface, мы также говорим, что они обратные вызовы. Они будут работать как информатор, но никогда не будут отправлять ссылки Activity или interface всегда использовать слабую ссылку в этих случаях.

Пожалуйста, обратитесь к скриншоту ниже, чтобы узнать, как это может вызвать проблемы.

Как вы можете видеть, начали ли мы AsyncTask с сильной ссылки, тогда нет гарантии, что наш Activity / Fragment будет до тех пор, пока мы не получим данные, поэтому было бы лучше использовать WeakReference в этих случаях, и это также поможет в управлении памятью, поскольку мы никогда не будем придерживаться сильной ссылки на наш Activity, тогда он будет иметь право на сбор мусора после его искажения.

Проверьте ниже фрагмент кода, чтобы узнать, как использовать awesome WeakReference -

MyTaskInformer.java Интерфейс, который будет работать как информатор.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.java AsyncTask выполняет длительную задачу, которая будет использовать WeakReference.

public class MySmallAsyncTask extends AsyncTask {

    // ***** Hold weak reference *****
    private WeakReference mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

    @Override
    protected String doInBackground(String... params) {

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

MainActivity.java Этот класс используется для запуска моего AsyncTask реализации interface в этом классе и override этот обязательный метод.

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

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

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}

86
задан ToolmakerSteve 9 November 2017 в 19:23
поделиться

7 ответов

Пересматривая этот вопрос, я теперь 'обнаружил' 5 различных способов сделать это, которые являются следующие:

System.ComponentModel.DesignMode property

System.ComponentModel.LicenseManager.UsageMode property

private string ServiceString()
{
    if (GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null) 
        return "Present";
    else
        return "Not present";
}

public bool IsDesignerHosted
{
    get
    {
        Control ctrl = this;

        while(ctrl != null)
        {
            if((ctrl.Site != null) && ctrl.Site.DesignMode)
                return true;
            ctrl = ctrl.Parent;
        }
        return false;
    }
}
public static bool IsInDesignMode()
{
    return System.Reflection.Assembly.GetExecutingAssembly()
         .Location.Contains("VisualStudio"))
}

Чтобы попытаться получить подвешивание на этих трех предложенных решениях, я создал немного тестового решения - с тремя проектами:

  • TestApp (приложение winforms),
  • SubControl (dll)
  • SubSubControl (dll)

Я затем встроил SubSubControl в SubControl, затем один из каждого в TestApp. Форма.

Этот снимок экрана показывает результат при выполнении. Screenshot of running

Этот снимок экрана показывает результат с формой, открытой в Visual Studio:

Screenshot of not running

Заключение: казалось бы, что без отражения единственным, которое надежно в конструкторе, является LicenseUsage, и единственным, который надежен вне конструктора, является 'IsDesignedHosted' (BlueRaja ниже)

PS: См. комментарий ToolmakerSteve ниже (который я не протестировал): "Обратите внимание, что ответ IsDesignerHosted был обновлен для включения LicenseUsage..., поэтому теперь тест может просто быть то, если (IsDesignerHosted). Альтернативный подход является тестом LicenseManager в конструкторе, и кэшируйте результат".

77
ответ дан Community 24 November 2019 в 08:02
поделиться

Почему Вы не проверяете LicenseManager. UsageMode. Это свойство может иметь значения LicenseUsageMode. Время выполнения или LicenseUsageMode. Время проектирования.

Вы, хотят, чтобы код только работал во времени выполнения, использовал следующий код:

if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
  bla bla bla...
}
29
ответ дан hopla 24 November 2019 в 08:02
поделиться

DesignMode является частной собственностью (от того, что я могу сказать). Ответ должен обеспечить общественную собственность, которая представляет опору DesignMode. Тогда Вы можете cascasde создавать резервную копию цепочки пользовательских элементов управления, пока Вы не сталкиваетесь с управлением лица, не использующего своего права или управлением, которое находится в режиме проектирования. Что-то вроде этого....

  public bool RealDesignMode()
  {
     if (Parent is MyBaseUserControl)
     {
        return (DesignMode ? true : (MyBaseUserControl) Parent.RealDesignMode;
     }

     return DesignMode;
  }

, Где все Ваши UserControls наследовались MyBaseUserControl. Кроме того, Вы могли реализовать интерфейс, который представляет "RealDeisgnMode".

обратите внимание, что этот код не является живым кодом, рядом с размышлениями манжеты.:)

1
ответ дан Craig 24 November 2019 в 08:02
поделиться

Я никогда не был пойман этим сам, но не могли, Вы просто идти создаете резервную копию Родительской цепочки от управления, чтобы видеть, установлен ли DesignMode где-нибудь выше Вас?

2
ответ дан Will Dean 24 November 2019 в 08:02
поделиться

Я не понял, что Вы не можете назвать Родителя. DesignMode (и я учился, что-то о 'защищенном' в C# также...)

Вот отражающая версия: (Я подозреваю, что могло бы быть преимущество производительности для создания designModeProperty статическое поле)

static bool IsDesignMode(Control control)
{
    PropertyInfo designModeProperty = typeof(Component).
      GetProperty("DesignMode", BindingFlags.Instance | BindingFlags.NonPublic);

    while (designModeProperty != null && control != null)
    {
        if((bool)designModeProperty.GetValue(control, null))
        {
            return true;
        }
        control = control.Parent;
    }
    return false;
}
1
ответ дан Will Dean 24 November 2019 в 08:02
поделиться

От эта страница :

( [Edit 2013] Отредактировано для работы в конструкторах с использованием метода, предоставленного @hopla)

/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode.  IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and http://stackoverflow.com/a/2693338/238419 )
/// </summary>
public bool IsDesignerHosted
{
    get
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            return true;

        Control ctrl = this;
        while (ctrl != null)
        {
            if ((ctrl.Site != null) && ctrl.Site.DesignMode)
                return true;
            ctrl = ctrl.Parent;
        }
        return false;
    }
}

Я отправил ошибку - отчет с Microsoft; Я сомневаюсь, что он куда-то пойдет, но все равно проголосуйте за него, так как это, очевидно, ошибка (независимо от того, это или нет ).

31
ответ дан 24 November 2019 в 08:02
поделиться

Я использую метод LicenseManager, но кэширую значение из конструктора для использования в течение всего жизненного цикла экземпляра.

public MyUserControl()
{
    InitializeComponent();
    m_IsInDesignMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}

private bool m_IsInDesignMode = true;
public bool IsInDesignMode { get { return m_IsInDesignMode; } }

Версия VB:

Sub New()
    InitializeComponent()

    m_IsInDesignMode = (LicenseManager.UsageMode = LicenseUsageMode.Designtime)
End Sub

Private ReadOnly m_IsInDesignMode As Boolean = True
Public ReadOnly Property IsInDesignMode As Boolean
    Get
        Return m_IsInDesignMode
    End Get
End Property
4
ответ дан 24 November 2019 в 08:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: