I'm getting the following exception:
android.app.Fragment$InstantiationException: Trying to instantiate a class com.example.android.btVspTest.StageCollectionFragment that is not a Fragment
The exception triggers within the following call to android.app.Activity.setContentView
from onCreate()
of my VspTestActivity
class, which extends android.app.Activity
:
setContentView(R.layout.activity_vsp_test);
My com.example.android.btVspTest.StageCollectionFragment
extends androidx.fragment.app.Fragment
. I am guessing the issue has to do with incompatibility beween android.app.Activity
and androidx.fragment.app.Fragment
. Is there a fix or work-around?
Application level build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 26
targetSdkVersion 29
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0'
/*implementation 'com.google.android.material:material:1.1.0-alpha08'*/
implementation 'androidx.viewpager2:viewpager2:1.0.0'
}
activity_vsp_test.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/test_layout">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/margin_huge"
android:orientation="horizontal">
<Button
android:id="@+id/test_connect_button"
android:layout_width="126dp"
android:layout_height="match_parent"
android:text="@string/connect" />
<Button
android:id="@+id/test_disconnect_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/disconnect" />
<Button
android:id="@+id/test_bluetooth_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="startBluetoothActivity"
android:text="Bluetooth" />
</LinearLayout>
<TextView
android:id="@+id/vsp_test_connection_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/disconnected" />
<TextView
android:id="@+id/test_result_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- 2 irrelevant linear layouts with buttons in them removed -->
<fragment class="com.example.android.btVspTest.StageCollectionFragment"
android:id="@+id/test_stage_collection_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
StageCollectionFragment.java:
package com.example.android.btVspTest;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;
import com.example.android.bluetoothvsp.R;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy;
public class StageCollectionFragment extends Fragment implements TabConfigurationStrategy {
// When requested, this adapter returns a StageFragment,
// representing an object in the collection.
StageCollectionAdapter demoCollectionAdapter;
ViewPager2 viewPager;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.test_stage_layout, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
demoCollectionAdapter = new StageCollectionAdapter(this);
viewPager = view.findViewById(R.id.test_stage_pager);
viewPager.setAdapter(demoCollectionAdapter);
TabLayout tabLayout = view.findViewById(R.id.test_stage_tab_layout);
new TabLayoutMediator(tabLayout, viewPager, this).attach();
}
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
tab.setText("OBJECT " + (position + 1));
}
}
VspTestActivity.java:
package com.example.android.btVspTest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.bluetoothvsp.ActivityMessageDataKey;
import com.example.android.bluetoothvsp.BluetoothActivity;
import com.example.android.bluetoothvsp.DeviceListActivity;
import com.example.android.bluetoothvsp.R;
import com.example.android.bluetoothvsp.enums.ConnectionState;
import com.example.android.bluetoothvsp.enums.TestState;
import com.example.android.common.logger.Log;
import com.example.android.common.logger.LogWrapper;
import com.example.android.common.logger.MessageOnlyLogFilter;
public class VspTestActivity extends Activity
{
/**
* Debugging.
*/
private static final String TAG = "VspTestActivity";
/**
* UI elements.
*/
private TextView mConnectionTextView;
private TextView mTestResultTextView;
private Button mConnectButton;
private Button mDisconnectButton;
private Button mSynchronousTestButton;
private Button mHostSpamButton;
private Button mReaderSpamButton;
private Button mBothSpamButton;
/**
* Objects provided by Android to facilitate Bluetooth operations.
*/
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
/**
* Manger used to start and handle the communication tests.
*/
private BluetoothVspTestManager mVspTestManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vsp_test);
if (savedInstanceState != null) {
return;
}
// Irrelevant code removed
}
// Irrelevant code removed
@Override
protected void onStart() {
super.onStart();
// Irrelevant code removed
}
// Irrelevant code removed
}
Some of the code is copy->paste->edit of example at https://developer.android.com/guide/navigation/navigation-swipe-view-2, with following mapping:
That developer.android.com example unfortunately isn't complete as the layout resources are missing. I haven't been able to find a full example on the internet, of combining TabLayout & ViewPager2.
I'm trying to do something like the draft screen at https://imgur.com/a/k8Tr52y?. I would eventually have 4 to 5 tabs with actual meaningful tab titles, with the tabs being added dynamically, and specific fragments in each of the tabs.
Since part of your code is using AndroidX libraries, I'll assume you are okay with going all-in and use AndroidX exclusively. You should. Right now, you are mixing old and new Android libraries and that's not a good thing. Simply do the following when declaring (pay attention to the import statements):
your activity:
import androidx.appcompat.app.AppCompatActivity;
public class VspTestActivity extends AppCompatActivity {
and your fragment:
import androidx.fragment.app.Fragment
public class StageCollectionFragment extends Fragment ...
Even easier is to let Android Studio do it all for you. Just select Refactor > Migrate to AndroidX (on the Mac)