Как вызвать функцию из другого класса с его контекстом (android, java) - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь перезагрузить viewPager всякий раз, когда пользователь нажимает кнопку внутри Item из viewPager.Соответствующие классы для этого случая SetupActivity и Adapter.В классе активности я уже сделал две функции для перезагрузки viewPager:

public void deleteSession(String title) {
        dbHelper = new DatabaseHelper(this);
        ((DatabaseHelper) dbHelper).deleteRow(title);
    }

и

public void refreshAdapter () {

        dbHelper = new DatabaseHelper(this); 
        Cursor dataCursor = ((DatabaseHelper) dbHelper).getData();
        models = new ArrayList<>(); 

        while (dataCursor.moveToNext()) { 
            models.add(new Model(
                    dataCursor.getString(1),
                    dataCursor.getInt(2),
                    dataCursor.getInt(3),
                    dataCursor.getInt(4)
            ));
        }
        adapter = new Adapter(models, this);
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(0, true);
    }

Таким образом, в основном deleteSession() удаляет определенный элемент из базы данных.refreshAdapter() читает обновленные данные из базы данных и устанавливает новый адаптер для viewPager.Эти функции работают нормально, если я вызываю их из события OnClick в классе SetupActivity.Однако, если я пытаюсь вызвать их из события OnClick в классе Adapter, приложение вылетает со следующими ошибками:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.content.ContextWrapper.getDatabasePath(ContextWrapper.java:327)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:352)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at com.example.android.slink.DatabaseHelper.getData(DatabaseHelper.java:69)
        at com.example.android.slink.SetupActivity.refreshAdapter(SetupActivity.java:436)
        at com.example.android.slink.Adapter$3.onClick(Adapter.java:111)
        at android.view.View.performClick(View.java:6669)
        at android.view.View.performClickInternal(View.java:6638)
        at android.view.View.access$3100(View.java:789)
        at android.view.View$PerformClick.run(View.java:26145)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6863)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Вот мой класс SetupActiviy (сокращен до соответствующих частей):

package com.example.android.slink;

public class SetupActivity extends AppCompatActivity {

    private SQLiteOpenHelper dbHelper;
    private SQLiteDatabase database;

    ViewPager viewPager;
    Adapter adapter;
    static ArrayList<Model> models;

    public void deleteSession(String title) {
        dbHelper = new DatabaseHelper(this);
        ((DatabaseHelper) dbHelper).deleteRow(title);
    }

    public void refreshAdapter () {
        dbHelper = new DatabaseHelper(this);
        Cursor dataCursor = ((DatabaseHelper) dbHelper).getData();
        models = new ArrayList<>();
        models.add(new Model("", 0,0,0));
        while (dataCursor.moveToNext()) {
            models.add(new Model(
                    dataCursor.getString(1),
                    dataCursor.getInt(2),
                    dataCursor.getInt(3),
                    dataCursor.getInt(4)
            ));
        }
        adapter = new Adapter(models, this);
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(0, true);
    }

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

        editTextScreenTitle = findViewById(R.id.editTextScreenTitle);
        relativeLayoutCard = findViewById(R.id.relativeLayoutCard);
        viewPager = findViewById(R.id.viewPager);

        dbHelper = new DatabaseHelper(this);
        Cursor dataCursor = ((DatabaseHelper) dbHelper).getData();

        models = new ArrayList<>();
        models.add(new Model("", 0,0,0));
        while (dataCursor.moveToNext()) {
            models.add(new Model(
                    dataCursor.getString(1),
                    dataCursor.getInt(2),
                    dataCursor.getInt(3),
                    dataCursor.getInt(4)
            ));
        }
        adapter = new Adapter(models, this);
        viewPager.setAdapter(adapter);
    }
}

Вот мой класс Adapter (также сокращен до соответствующих частей):

package com.example.android.slink;

public class Adapter extends PagerAdapter {

    private List<Model> models;
    private LayoutInflater layoutInflater;
    private Context context;

    SetupActivity setupActivity = new SetupActivity();

    public Adapter(List<Model> models, Context context) {
        this.models = models;
        this.context = context;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
        layoutInflater = LayoutInflater.from(context);
        final View view = layoutInflater.inflate(R.layout.item, container, false);

        TextView buttonDeleteCard = view.findViewById(R.id.textViewDeleteCard);

        buttonDeleteCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setupActivity.deleteSession([...some title...]);
                setupActivity.refreshAdapter();
            }
        });

        container.addView(view, 0);
        return view;
    }
}

Я думаю, что он имеет какое-то отношение к контексту.Должен ли я передавать контекст из SetupActiity в класс Adapter и, если да, как мне это сделать?Или это невозможно, и мне нужно перехватить событие OnClick в классе Adapter из класса SetupActivity?Я новичок в программировании на Java и буду очень признателен, если кто-нибудь из вас сможет мне помочь, решить эту проблему!

1 Ответ

0 голосов
/ 25 февраля 2019

Измените Adapter следующим образом:

public class Adapter extends PagerAdapter {

    private List<Model> models;
    private LayoutInflater layoutInflater;
    private Context context;

    private SetupActivity setupActivity;

    public Adapter(List<Model> models, Context context) {
        this.models = models;
        this.context = context;
        setupActivity = (SetupActivity) context;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
        layoutInflater = LayoutInflater.from(context);
        final View view = layoutInflater.inflate(R.layout.item, container, false);

        TextView buttonDeleteCard = view.findViewById(R.id.textViewDeleteCard);

        buttonDeleteCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setupActivity.deleteSession([...some title...]);
                setupActivity.refreshAdapter();
            }
        });

        container.addView(view, 0);
        return view;
    }
}

Почему возникла ошибка?

Вы передаете Context из SetupActivity в Adapter, вы сохраняете эту ссылку в поле (context), но по ошибке создали новый экземпляр SetupActivity.

Вот почему вы получили NullPointerException.Активность ваша Context.Это наследует от этого.Так что просто приведите его в свой конструктор и используйте позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...