Активность заполняет ActionBar в его методе onCreateOptionsMenu()
.
Вместо использования setcustomview()
просто переопределите onCreateOptionsMenu
следующим образом:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
Если выбрано действие в ActionBar, вызывается метод onOptionsItemSelected()
. Он получает выбранное действие в качестве параметра. На основании этой информации ваш код может решить, что делать, например:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menuitem1:
Toast.makeText(this, "Menu Item 1 selected", Toast.LENGTH_SHORT).show();
break;
case R.id.menuitem2:
Toast.makeText(this, "Menu item 2 selected", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
Возможно, вам стоит попробовать это со статическим методом, который возвращает экземпляр объекта.
var myClass = MyClass.LoadFromDirectory(@"C:\temp");
Это сохранит код инициализации вне вашего конструктора, а также даст вам это " однострочное объявление, которое вы ищете.
Переходя к комментарию снизу к плакату, добавив State, реализация может выглядеть так:
public class MyClass
{
#region Constructors
public MyClass(string directory)
{
this.Directory = directory;
}
#endregion
#region Properties
public MyClassState State {get;private set;}
private string _directory;
public string Directory
{
get { return _directory;}
private set
{
_directory = value;
if (string.IsNullOrEmpty(value))
this.State = MyClassState.Unknown;
else
this.State = MyClassState.Initialized;
}
}
#endregion
public void LoadFromDirectory()
{
if (this.State != MyClassState.Initialized || this.State != MyClassState.Loaded)
throw new InvalidStateException();
// Do loading
this.State = MyClassState.Loaded;
}
}
public class InvalidStateException : Exception {}
public enum MyClassState
{
Unknown,
Initialized,
Loaded
}
Это зависит от обстоятельств. Вы должны оценить основную цель занятия. Какую функцию он выполняет?
Я обычно предпочитаю, чтобы конструктор класса выполнял инициализацию, необходимую для функционирования класса. Затем я вызываю методы класса, которые могут с уверенностью предположить, что необходимая инициализация была выполнена.
Как правило, фаза инициализации не должна быть слишком интенсивной. Альтернативный способ сделать это может быть следующим:
// Instantiate the class and get ready to load data from files.
MyClass myClass = new MyClass(@"C:\temp");
// Parse the file collection and load necessary data.
myClass.PopulateData();
Это все, что делает ваш класс? Если так, то я бы сказал, что это не имеет значения. Но вполне вероятно, что ваш класс на самом деле делает больше, чем вы показали. Например, есть ли в нем обработка ошибок?
Назначение конструктора - создать объект. Цель метода - выполнить действие. Итак, я голосую за эту форму:
MyClass myClass = new MyClass();
myClass.LoadFromDirectory(@"C:\temp");
Я согласен с Ари и другими - разделите их.
Конструктор действительно должен выполнять минимальный объем работы (просто инициализировать объект, готовый к использованию, и оставить все как есть ). Используя отдельный метод для выполнения работы:
Я думаю, вам следует выбрать один из двух подходов, описанных выше ("сначала инициализировать, затем выполнить" vs "пустой init, выполнить с параметрами") в зависимости от того, планируете ли вы повторно использовать один и тот же объект для выполнения той же операции с разные входные данные.
если класс используется только для выполнения задачи с фиксированным параметром, я бы инициализировал его в конструкторе (сделав его доступным только для чтения), а затем выполнял задачу другим методом.
Если вы хотите продолжить выполнение задачи с разными параметрами, я бы поместил ее в метод задачи.
Если весь класс выполняет эту задачу, я бы также рассмотрел возможность изменения всего этого на статический класс / методы - ему не нужно сохранять внутреннее состояние.
В любом случае, я бы никогда не поместил саму задачу в конструктор. Как сказал Церебрус, инициализация должна быть быстрой.
Если основной целью вашего класса не является выполнение ввода-вывода, вам, вероятно, не следует выполнять операции ввода-вывода (потенциально генерируя IOException) в конструкторе.
Рассмотрите возможность разделения класса пополам:
interface IMyDataSource
{
// ...
}
class FileDataSource: IMyDataSource
{
public FileDataSource(string path)
{
// ...
}
}
class MyClass
{
public MyClass(IMyDataSource source)
{
// ...
}
}
IMyDataSource myDS = new FileDataSource(@"C:\temp");
MyClass myClass = new MyClass(myDS);
Таким образом, основной класс может сосредоточиться на управлении своим собственным состоянием, в то время как источник данных строит начальное состояние из содержимого файла.
Если это единственный ресурс, с которым работает класс, вероятно, лучше передать путь конструктору. В противном случае это был бы параметр для ваших учеников.
Лично я предпочитаю использовать инициализаторы C # 3.0.
class MyClass {
public string directory;
public void Load() {
// Load files from the current directory
}
}
MyClass myClass = new MyClass{ directory = @"C:\temp" };
myClass.Load();
Это дает несколько преимуществ:
Я собираюсь повторить здесь, ребята, "разделите их". Если это поможет, попробуйте следующее:
Применяя это здесь, вы получаете следующее:
Это похоже на мне было бы намного логичнее, чем «Конструктор должен создать объект и загрузить его данные из файловой системы.