Виджет не обрабатывает событие click [duplicate]

Давайте рассмотрим некоторые простые примеры методов магии __getattr__ и __getattribute__.

__getattr__

Python будет вызывать метод __getattr__ всякий раз, когда вы запрашиваете атрибут, еще не определена. В следующем примере мой класс Count не имеет метода __getattr__. Теперь, когда я пытаюсь получить доступ к атрибутам obj1.mymin и obj1.mymax, все работает нормально. Но когда я пытаюсь получить доступ к атрибуту obj1.mycurrent - Python дает мне AttributeError: 'Count' object has no attribute 'mycurrent'

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

Теперь мой класс Count имеет метод __getattr__. Теперь, когда я пытаюсь получить доступ к атрибуту obj1.mycurrent, python возвращает мне все, что я реализовал в моем методе __getattr__. В моем примере, когда я пытаюсь вызвать атрибут, который не существует, python создает этот атрибут и устанавливает его в целочисленное значение 0.

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

Теперь давайте см. метод __getattribute__. Если у вас есть метод __getattribute__ в вашем классе, python вызывает этот метод для каждого атрибута независимо от того, существует он или нет. Итак, почему нам нужен метод __getattribute__? Одна из веских причин заключается в том, что вы можете запретить доступ к атрибутам и сделать их более безопасными, как показано в следующем примере.

Всякий раз, когда кто-то пытается получить доступ к моим атрибутам, которые начинаются с подстановки «cur» python вызывает AttributeError исключение , В противном случае он возвращает этот атрибут.

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

Важно: чтобы избежать бесконечной рекурсии в методе __getattribute__, ее реализация всегда должна вызывать метод базового класса с тем же именем для доступа к любым атрибутам, которые ему нужны. Например: object.__getattribute__(self, name) или super().__getattribute__(item), а не self.__dict__[item]

ВАЖНО

Если ваш класс содержит как методы getattr, так и getattribute magic, тогда __getattribute__ вызывается первым. Но если __getattribute__ вызывает исключение AttributeError, исключение будет проигнорировано, и будет вызван метод __getattr__. См. Следующий пример:

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
14
задан SweSnow 13 January 2013 в 01:49
поделиться

2 ответа

Посмотрите здесь и прокрутите до подзаголовка. Добавление поведения к отдельным элементам.

Вам нужно убедиться, что вы вызываете оба setPendingIntentTemplate() из вашего AppWidgetProvider и setOnClickFillInIntent() из вашей реализации RemoteViewsService.RemoteViewsFactory.

Например:

public class Widget extends AppWidgetProvider {

    // ...

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        for(int i = 0; i < appWidgetIds.length; i++){

            RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget);

            Intent startActivityIntent = new Intent(context, myActivity.class);
            PendingIntent startActivityPendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            widget.setPendingIntentTemplate(R.id.list_view, startActivityPendingIntent);

            appWidgetManager.updateAppWidget(appWidgetIds[i], widget);

            // ...
    }
}

public class WidgetAdapter implements RemoteViewsService.RemoteViewsFactory {

    // ...

    @Override
    public RemoteViews getViewAt(int position) {

    RemoteViews widgetRow = new RemoteViews(context.getPackageName(), R.layout.widget_row);

        Intent fillInIntent = new Intent();
        fillInIntent.putExtra(Widget.EXTRA_LIST_VIEW_ROW_NUMBER, position);
        widgetRow.setOnClickFillInIntent(R.id.list_view_row, fillInIntent);

        // ...

        return widgetRow;
    }
}

В примере StackWidget есть более убедительный пример, который находится в SDK , хотя мне было трудно найти (см. здесь для направлений). Он создает намерение показывать сообщение Toast, но использует тот же код.

36
ответ дан AtaerCaner 21 August 2018 в 23:53
поделиться

Чтобы запустить любое действие, вы создаете намерение, а затем вызываете startActivity по этому намерению. Проверьте намерение и startActivity, и я уверен, что вы сможете сделать это сами.

-9
ответ дан Run2 21 August 2018 в 23:53
поделиться
  • 1
    Конечно, я знаю, как запустить свою деятельность обычным способом. Мне интересно, как вы это сделаете с помощью виджета ListView, поскольку обычный PendingIntent не будет работать. – SweSnow 13 January 2013 в 10:33
Другие вопросы по тегам:

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