首页 > 解决方案 > 当我使用 ListView 和自定义 ArrayAdapter 启动活动时,Android 应用程序崩溃

问题描述

我创建了一个 Location 类,当我在 MainActivity 中单击 Cinemas 时,我想打开另一个包含 Location 对象列表的活动。为此,我创建了一个自定义 location_list_item 布局文件和一个自定义 ArrayAdapter。出于某种原因,当我点击电影院时,我的应用程序崩溃了。为什么?

MainActivity.java

package com.example.android.tourguide;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

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

        View cinemasView = findViewById(R.id.cinemas_layout);

        cinemasView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,
                        CinemasActivity.class);
                startActivity(intent);
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#fff8e1"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_activity_title"
        android:textSize="30sp"
        android:textStyle="bold"
        android:textColor="@android:color/black"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="16dp"/>

    <LinearLayout
        android:id="@+id/cinemas_layout"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="#4a148c">

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:src="@drawable/category_cinemas"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="16dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/category_cinemas"
            android:textSize="25sp"
            android:textColor="@android:color/white"/>
    </LinearLayout>

    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="@android:color/darker_gray" />

    <LinearLayout
        android:id="@+id/restaurants_layout"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="#4a148c">

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:src="@drawable/category_restaurants"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="16dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/category_restaurants"
            android:textSize="25sp"
            android:textColor="@android:color/white"/>
    </LinearLayout>

    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="@android:color/darker_gray" />

    <LinearLayout
        android:id="@+id/gyms_layout"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="#4a148c">

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:src="@drawable/category_gyms"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="16dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/category_gyms"
            android:textSize="25sp"
            android:textColor="@android:color/white"/>
    </LinearLayout>

    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="@android:color/darker_gray" />

    <LinearLayout
        android:id="@+id/parks_layout"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#4a148c">

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:src="@drawable/category_parks"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="16dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="@string/category_parks"
            android:textSize="25sp"
            android:textColor="@android:color/white"/>
    </LinearLayout>

</LinearLayout>

location_category_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/location_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/location_hours_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="Hours"
        android:textStyle="bold"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/location_working_days"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            tools:text="Every Day" />

        <TextView
            android:id="@+id/location_working_hours"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="16dp"
            tools:text="09:00 –  00:00" />

    </LinearLayout>

    <TextView
        android:id="@+id/location_address_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="Address"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/location_address"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        tools:text="09:00 –  00:00" />

    <TextView
        android:id="@+id/location_phone_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="Phone"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/location_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        tools:text="+7 (555) 555-55-55" />

</LinearLayout>

位置.java

package com.example.android.tourguide;

import androidx.annotation.NonNull;

public class Location {
    private int mImageResourceId;
    private String mAddress;
    private String mPhone;
    private String mWorkingDays;
    private String mWorkingHours;

    public Location(int imageResourceId, String address, String phone,
                    String workingDays, String workingHours) {
        mImageResourceId = imageResourceId;
        mAddress = address;
        mPhone = phone;
        mWorkingDays = workingDays;
        mWorkingHours = workingHours;
    }

    public int getImageResourceId() {
        return mImageResourceId;
    }

    public String getAddress() {
        return mAddress;
    }

    public String getPhone() {
        return mPhone;
    }

    public String getWorkingDays() {
        return mWorkingDays;
    }

    public String getWorkingHours() {
        return mWorkingHours;
    }

    @NonNull
    @Override
    public String toString() {
        return mImageResourceId + mAddress + mWorkingDays + mWorkingDays + mPhone;
    }
}

LocationAdapter.java

package com.example.android.tourguide;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

public class LocationAdapter extends ArrayAdapter<Location> {
    /**
     * This is our own custom constructor (it doesn't mirror a superclass constructor).
     * The context is used to inflate the layout file, and the list is the data we want
     * to populate into the lists.
     *
     * @param context The current context. Used to inflate the layout file.
     * @param locations A List of Location objects to display in a list
     */

    public LocationAdapter(Activity context, ArrayList<Location> locations) {
        // Here, we initialize the ArrayAdapter's internal storage for the context and the list.
        // the second argument is used when the ArrayAdapter is populating a single TextView.
        // Because this is a custom adapter for one ImageView and 4 TextViews, the adapter is not
        // going to use this second argument, so it can be any value. Here, we used 0.
        super(context, 0, locations);
    }

    /**
     * Provides a view for an AdapterView (ListView, GridView, etc.)
     *
     * @param position The position in the list of data that should be displayed in the
     *                 list item view.
     * @param convertView The recycled view to populate.
     * @param parent The parent ViewGroup that is used for inflation.
     * @return The View for the position in the AdapterView.
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Check if the existing view is being reused, otherwise inflate the view
        View listItemView = convertView;
        if (listItemView == null)
        {
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.location_category_list_item, parent,
                    false);
        }

        // Get the {@link Location} object located at this position in the list
        Location currentLocation = getItem(position);

        // Find the ImageView in the location_category_list_item.xml layout
        // with the ID location_image
        ImageView image = listItemView.findViewById(R.id.location_image);
        // Get the image resource ID from the current Location object and
        // set the image to imageView
        image.setImageResource(currentLocation.getImageResourceId());

        // Find the TextView in the location_category_list_item.xml layout
        // with the ID location_working_days
        TextView workingDaysTextView = listItemView.findViewById(R.id.location_working_days);
        // Get the working days from the current Location object and
        // set this text on the workingDaysTextView
        workingDaysTextView.setText(currentLocation.getWorkingDays());

        // Find the TextView in the location_category_list_item.xml layout
        // with the ID location_working_hours
        TextView workingHoursTextView = listItemView.findViewById(R.id.location_working_hours);
        // Get the working hours from the current Location object and
        // set this text on the workingHoursTextView
        workingHoursTextView.setText(currentLocation.getWorkingHours());

        // Find the TextView in the location_category_list_item.xml layout
        // with the ID location_address
        TextView addressTextView = listItemView.findViewById(R.id.location_address);
        // Get the address from the current Location object and
        // set this text on the addressTextView
        addressTextView.setText(currentLocation.getAddress());

        // Find the TextView in the location_category_list_item.xml layout
        // with the ID location_phone
        TextView phoneTextView = listItemView.findViewById(R.id.location_phone);
        // Get the address from the current Location object and
        // set this text on the phoneTextView
        phoneTextView.setText(currentLocation.getPhone());

        // Return the whole list item layout
        // so that it can be shown in the ListView
        return listItemView;
    }
}

CinemasActivity.java

package com.example.android.tourguide;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;

public class CinemasActivity extends AppCompatActivity {

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

        //Create a list of cinemas
        final ArrayList<Location> locations = new ArrayList<>();
        locations.add(new Location(R.drawable.cinemas_byl,
                "Zhukova mikrorayon, 38",
                "+7 (929) 002-20-09",
                "Every Day",
                "09:00 – 00:00"));
        locations.add(new Location(R.drawable.cinemas_charly,
                "Ol'minskogo mikrorayon, 17",
                "+7 (472) 523-34-56",
                "Every Day",
                "09:30 – 02:00"));
        locations.add(new Location(R.drawable.cinemas_cinema_5,
                "Molodezhnyy Proyezd, 10",
                "+7 (472) 523-37-27",
                "Every Day",
                "09:00 – 00:00"));


        // Create an {@link LocationAdapter}, whose data source is a list of
        // {@link Locations}. The adapter knows how to create list item views
        // for each item in the list.
        LocationAdapter locationAdapter = new LocationAdapter(this, locations);

        // Get a reference to the ListView, and attach the adapter to the listView.
        ListView listView = (ListView) findViewById(R.id.list);
        listView.setAdapter(locationAdapter);

    }
}

堆栈跟踪

标签: javaandroid

解决方案


可能您在CinemasActivity.

setContentView(R.layout.location_category_list_item);

R.layout.location_category_list_item是您的 ListView 的项目视图。

没有ListView导致location_category_list_item崩溃的原因


推荐阅读