2012-06-27 5 views
38

Мне часто приходится обращаться к методам, требующим ссылки на некоторые действия. Например, чтобы использовать getWindowManager, мне нужно получить доступ к некоторым Activity. Но часто мой код для использования этих методов находится в каком-то другом классе, который не имеет ссылки на действие. До сих пор я либо сохранил ссылку на основное действие, либо передал контекст некоторой активности классу. Есть ли лучший способ сделать это?Как ссылаться на текущее или основное действие из другого класса

+0

+1 Это отличный вопрос! Это проблема, с которой сталкиваются многие разработчики: как я могу понять, что такое текущая (или «верхняя») активность? –

+8

Мое личное мнение состоит в том, что он отстой, что Google не сделал простой метод API для доступа к активному действию в настоящий момент, независимо от того, где вы находитесь в коде. В конце концов, Android знает, что это такое, и отслеживает его. Почему бы не быть приятным для всех нас, бедных мальчиков, и давайте в нем :-( – AndroidDev

+0

, если вам нужны какие-то методы из всех ваших действий, которые делают то же самое, не было бы лучше создать абстрактный класс который реализует все эти методы и позволяет вашей деятельности извлекать из этого? Или я ошибаюсь? – herom

ответ

11

Проходящий контекст - лучший способ для рефренса.

Вы можете передать Контекст другому классу.

В деятельности ::

AnotherClass Obj = new AnotherClass(this); 

в другом классе

class AnotherClass{ 

public AnotherClass(Context Context){ 

    } 

} 
+0

Но если есть несколько загруженных действий, только один из них будет активен в любой момент, поэтому я подозреваю, что есть способ получить доступ ко всему, что происходит в курсе nt без необходимости проходить контекст. – AndroidDev

+1

Пожалуйста, объясните, почему это лучший способ? – Slawa

2

Есть много способов для такой деятельности.

вы можете использовать:

  • startActivityForResult метод

  • система радиосообщений и приемника (вы можете транслировать события из реальной деятельности, а также зарегистрировать приемник в целевой активности. Помните, что целевая активность должна быть предварительно инициализирована и не завершена)

  • Как вы говорите, храните ссылку на целевую деятельность, где вам нужно.
+1

Я не хочу общения. Просто ссылка. – AndroidDev

5

Вы можете реализовать необходимые методы в своей деятельности и реализовать Handler. Затем просто передайте экземпляр обработчика в свои классы, где вы можете получить сообщение для обработчика и отправить его в целевую.

+0

Если я собираюсь это сделать, я мог бы просто передать контекст активности классу. – AndroidDev

0

Ручка Intent в классе вы хотите, чтобы сделать эти методы, и отправить ему информацию в Bundle, как так:

Intent i = new Intent("android.intent.action.MAIN"); 
    i.setComponent(new ComponentName("com.my.pkg","com.my.pkg.myActivity")); 
    Bundle data = new Bundle(); 

    i.putExtras(data); 

    startActivityForResult(i); 

Затем с помощью OnActivityResultListener, чтобы захватить новые данные.

+0

Нет, это не то, что я ищу. Все, что я хочу, это ссылка на то, что происходит в текущей деятельности, или на главную. У вас может быть классный вызов класса и достаточно глубокий. Не должно быть необходимости передавать контекст каждому классу. – AndroidDev

3

Вы можете сделать вас экземпляр приложения синглтона, и использовать его, когда вам нужно контекст

Примером может служить в этом вопросе:
Android Application as Singleton

Таким образом, когда вам нужен контекст, вы можете получить его с
Context context = MyApplication.getInstance()

Это не может быть чистым решением, но это работает хорошо для меня до сих пор

+0

Не работал бы, если бы я писал классы и отдавал их кому-то другому, кто не мог использовать Синглтон. – AndroidDev

+0

Это правда ... :( –

-3

Просто догадаться, так как я этого не сделал, но это может сработать.

1) Получите ваш applicationContext, создав класс Android Application Singleton.

2) Получите свой класс ActivityManager из контекста.

3) Получите список RunningTaskInfos, используя getRunningTasks() в ActivityManager.

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

5) Вызов topActivity на этом RunningTaskInfo, который должен вернуть вам верхнюю активность в стеке действий для этой задачи.

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

+0

Почему нисходящее? Объяснение было бы приятным ... – onit

+0

Я не дал вам нисходящее, но ... одна из проблем с этим методом заключается в том, что вам нужны разрешения для getRunningTasks() и что пугает многих пользователей. –

+0

@DavidWasser Это правда, я не рекомендую этот подход, но я разместил его больше, чтобы показать, какую работу вам нужно пройти, чтобы получить текущую активность из стека без ссылка – onit

1

Мы построили каркас для этого. У нас есть класс BaseActivity, который наследует от Activity, и он переопределяет все методы жизненного цикла и содержит некоторые статические (классные) переменные, которые отслеживают стек действий. Если что-то хочет знать, что такое текущая активность, он просто вызывает статический метод в BaseActivity, который возвращает активность поверх нашего приватно управляемого стека.

Это своего рода хакерство, но оно работает. Я не уверен, что порекомендую его.

10

Если у вас уже есть действительный контекст, просто используйте: Activity activity = (Activity) context;

+0

Если контекст не является приложением, в этом случае это вызовет исключение ClassCastException. – nasch

+1

Да, это не всегда работает, вы должны быть уверены, что то, что вы делаете, - это действие или вы будете иметь classCastException. Для этого вы можете сделать «if (context instanceOf Activity) {// перейти к cast}» –

+0

@AleMuzzi вы сохранили мое время. Спасибо +1 vo te for u –

0

Я новичок в андроид так мое предложение может выглядеть Guffy, но что, если вы просто создать ссылку на свою деятельность как частный свойство и назначить это в методе OnCreate? Вы даже можете создать свою CustomActivity с помощью OnCreate и получить все свои действия из своей CustomActivity, а не общей деятельности, предоставляемой adnroid.

class blah extends Activity{ 
 
    private Activity activityReference; 
 
    public void onCreate(Bundle savedInstanceState) { 
 
     super.onCreate(savedInstanceState); 
 
     activityReference = this; 
 
    } 
 

 
}
после того, что вы могли бы использовать это, как вы хотите, то есть в

Intent i = new Intent(activityReference, SomeOtherActivity.class) 

и т.д.

3

Я нашел способ, чтобы получить активность к классу неактивности, что Я не видел обсуждаемых на форумах. Это произошло после многочисленных неудачных попыток использования getApplicationContext() и передачи контекста в качестве параметра для конструкторов, ни одна из которых не дала Activity. Я видел, что мои адаптеры были заливкой входящего контекста деятельности, поэтому я сделал то же приведение к моим неактивности класса конструкторам:

public class HandleDropdown extends Application{ 
... 
    public Activity activity; 
... 
public HandleDropdown() { 
    super(); 
} 
public HandleDropdown(Activity context) { 
    this.activity = context; 
    this.context = context; 
} 
public void DropList(View v,Activity context) { 
    this.activity = context; 
    this.context = context; 
... 
} 

После выполнения этого броска преобразования контекста в операцию я мог бы использовать this.activity везде, где я необходим контекст активности.

0

Я решил это, сделав класс singleton экземпляром класса ниже в качестве члена.

public class InterActivityReferrer <T> { 
    HashMap<Integer, T> map; 
    ArrayList<Integer> reserve; 

    public InterActivityReferrer() { 
     map = new HashMap<>(); 
     reserve = new ArrayList<>(); 
    } 

    public synchronized int attach(T obj) { 
     int id; 
     if (reserve.isEmpty()) { 
      id = reserve.size(); 
     } 
     else { 
      id = reserve.remove(reserve.size() - 1); 
     } 

     map.put(id, obj); 
     return id; 
    } 

    public synchronized T get(int id) { 
     return map.get(id); 
    } 

    public synchronized T detach(int id) { 
     T obj = map.remove(id); 
     if (obj != null) reserve.add(id); 
     return obj; 
    } 
} 

Этот класс может получить объект T и вернуть уникальное целое число, присвоенное объекту attach(). Назначенные целые числа не будут сталкиваться друг с другом, если HashMap не сработает. Каждое присваиваемое целое число будет освобождено, когда его соответствующий объект будет отсоединен командой detach(). Свободные целые числа будут использоваться повторно при подключении нового объекта.

И от одноплодной класса:

public class SomeSingleton { 
    ... 
    private InterActivityReferrer<Activity> referrer = new InterActivityReferrer<>(); 
    ... 
    public InterActivityReferrer<Activity> getReferrer() {return referrer;} 
} 

И от деятельности, которую необходимо отнести:

... 
    int activityID = SomeSingleton.getInstance().getReferrer().attach(this); 
    ... 

Теперь с этим, уникальное целое число, соответствующее этому экземпляру деятельности возвращается. И целое число может быть доставлено в другую начальную активность, используя Intent и putExtra().

... 
    Intent i = new Intent(this, AnotherActivity.class); 
    i.putExtra("thisActivityID", activityID); 
    startActivityForResult(i, SOME_INTEGER); 
    ... 

И от другой деятельности:

... 
    id refereeID = getIntent().getIntExtra("thisActivityID", -1); 
    Activity referredActivity = SomeSingleton.getInstance().getReferrer().get(refereeID); 
    ... 

И, наконец, эта деятельность может быть передан. И InterActivityReferrer может использоваться для любого другого класса.

Надеюсь, это поможет.

0
public static Activity getLaunchActivity() 
{ 
    final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread"); 

    final Method methodApp = activityThreadClass.getMethod("currentApplication"); 
    App = (Application) methodApp.invoke(null, (Object[]) null); 
    Intent launcherIntent = App.getPackageManager().getLaunchIntentForPackage(App.getPackageName()); 
    launchActivityInfo = launcherIntent.resolveActivityInfo(App.getPackageManager(), 0); 
    Class<?> clazz; 
    try 
    { 
     clazz = Class.forName(launchActivityInfo.name); 
     if(clazz != null) 
      return Activity.class.cast(clazz.newInstance()); 
    } 
    catch (Exception e) 
    {} 

    return null; 
} 
+1

Пожалуйста, добавьте некоторое объяснение того, что делает ваш код. –

Смежные вопросы