无法从MainActivity类

时间:2018-07-18 05:35:46

标签: android android-layout android-gui

我正在制作一个图像下载Android应用程序,该应用程序需要一定数量的图像URL,为提供的URL数量创建所需的GUI,然后显示它们。我成功地做到了。现在,我正在尝试分离此任务的模块。为了做到这一点,我想做所有MainActivity类之外的事情。 MainActivity类仅以url形式提供输入,然后将结果取回并显示出来。

JAVA代码: MainActivity类:

public class MainActivity extends AppCompatActivity {


    ArrayList<String> urls = new ArrayList<>();

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

        addUrls();
   }

   public void downloadImages(View view){
       Manager manager = new Manager(MainActivity.this,urls);
       manager.downloadImages();
   }

    public void addUrls() {

        urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXEZRoYOhIJxL5foNz_NlatDlgYStzZgVIiKuo6vtRtz2wY-8b4Q");
        urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFL3WYbqNOX-dwjtT1LroBlY5W-3YuwSIuCMRaLpnjMXbVPEJy");
        urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQiwgrJeAJN-7lcy92N51uP7XzccK_p-fTSJNCXPLPSVih8wqPf");
        urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT19dYLCEZlMRqojedJB-05jTrflD74nasvkXs-SdVeyM2BEpCSFA");
        urls.add("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg");
        urls.add("https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg");
        urls.add("https://images.unsplash.com/photo-1418489098061-ce87b5dc3aee?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=2f033882f3c25404e3f904fbfe2351be&w=1000&q=80");
        urls.add("https://techcrunch.com/wp-content/uploads/2018/03/gettyimages-705351545.jpg?w=730&crop=1");

    }
}

Manager类(充当管理器或GUI制作类的类):

class Manager {

    private Context context;
    private ArrayList<String> urls = new ArrayList<>();

    LinearLayout linearLayoutScrollView;

    ImageView imageView;
    ProgressBar progressBar;
    RelativeLayout relativeLayout;

    ImageDownloader imageDownloader;
    public Manager(Context context, ArrayList<String> urls) {
        this.context = context;
        this.urls = urls;
    }

    public void buildUI() {
        System.out.println("Error # 1");
        imageView = new ImageView(context);
        imageView.setVisibility(View.GONE);

        System.out.println("Error # 2");
        progressBar = new ProgressBar(context);
        progressBar.setIndeterminate(true);
        progressBar.setVisibility(View.GONE);

        System.out.println("Error # 3");
        relativeLayout = new RelativeLayout(context);
        relativeLayout.addView(imageView);
        relativeLayout.addView(progressBar);

        System.out.println("Error # 4");
        linearLayoutScrollView = (LinearLayout) findViewById(R.id.linearLayoutScrollView);
        linearLayoutScrollView.addView(relativeLayout);
        System.out.println("Error # 5");

    }

    public void downloadImages() {
        for (int i = 0; i < urls.size(); i++) {

            buildUI();

            imageDownloader = new ImageDownloader(imageView,progressBar,imageDownloader);

            progressBar.setVisibility(View.VISIBLE);

            imageDownloader.execute(urls.get(i));

        }
    }    
}

ImageDownloader类:

public class ImageDownloader extends AsyncTask<String, Void, Bitmap> {

    ImageView imageView;
    ProgressBar progressBar;
    ImageDownloader imageDownloader;

    public ImageDownloader(ImageView imageView, ProgressBar progressBar, ImageDownloader imageDownloader) {
        this.imageView = imageView;
        this.progressBar = progressBar;
        this.imageDownloader = imageDownloader;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        imageView.setVisibility(View.GONE);
        progressBar.setVisibility(View.VISIBLE);
    }


    @Override
    protected Bitmap doInBackground(String... params) {
        try {
            URL url = new URL(params[0]);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            System.out.println("Content Type = " + connection.getContentType());
            if (connection.getContentType().contains("image")) {
                InputStream inputStream = connection.getInputStream();
                return BitmapFactory.decodeStream(inputStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        try {
            imageView.setImageBitmap(bitmap);
            progressBar.setVisibility(View.GONE);
            imageView.setVisibility(View.VISIBLE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

XML代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="match_parent"
    tools:context="com.example.syeddanish.downloadingimages.MainActivity">

    <LinearLayout
        android:id="@+id/buttonsLinearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <Button
            android:id="@+id/downloadImagesButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="downloadImages"
            android:text="Download Images" />

        <Button
            android:id="@+id/resetButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="reset"
            android:text="Reset" />

    </LinearLayout>

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/buttonsLinearLayout">

        <LinearLayout
            android:id="@+id/linearLayoutScrollView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" />
    </ScrollView>


</RelativeLayout>

问题在于,在“管理器”类中,它为findViewById()方法中的“向方法添加限定符”提供了错误。

linearLayoutScrollView = (LinearLayout) findViewById(R.id.linearLayoutScrollView);

如果我添加此预选赛,它将像上面那样更改上面的行

linearLayoutScrollView = (LinearLayout) linearLayoutScrollView.findViewById(R.id.linearLayoutScrollView);

,然后给出错误 日志猫:

  

E / Android运行时:致命异常:主要                                                                                                 流程:com.example.syeddanish.downloadingimages,PID:29339                                                                                                 java.lang.IllegalStateException:无法执行以下方法   android:onClick                                                                                                     在   android.support.v7.app.AppCompatViewInflater $ DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)                                                                                                     在android.view.View.performClick(View.java:6291)                                                                                                     在android.view.View $ PerformClick.run(View.java:24931)                                                                                                     在android.os.Handler.handleCallback(Handler.java:808)                                                                                                     在android.os.Handler.dispatchMessage(Handler.java:101)                                                                                                     在android.os.Looper.loop(Looper.java:166)                                                                                                     在android.app.ActivityThread.main(ActivityThread.java:7425)                                                                                                     在java.lang.reflect.Method.invoke(本机方法)                                                                                                     在   com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:245)                                                                                                     在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)                                                                                                  造成原因:java.lang.reflect.InvocationTargetException                                                                                                     在java.lang.reflect.Method.invoke(本机方法)                                                                                                     在   android.support.v7.app.AppCompatViewInflater $ DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)                                                                                                     在android.view.View.performClick(View.java:6291)                                                                                                     在android.view.View $ PerformClick.run(View.java:24931)                                                                                                     在android.os.Handler.handleCallback(Handler.java:808)                                                                                                     在android.os.Handler.dispatchMessage(Handler.java:101)                                                                                                     在android.os.Looper.loop(Looper.java:166)                                                                                                     在android.app.ActivityThread.main(ActivityThread.java:7425)                                                                                                     在java.lang.reflect.Method.invoke(本机方法)                                                                                                     在   com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:245)                                                                                                     在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)                                                                                                  原因:java.lang.NullPointerException:尝试调用虚拟   方法'android.view.View   空对象上的android.widget.LinearLayout.findViewById(int)'   参考                                                                                                     在   com.example.syeddanish.downloadingimages.Manager.buildUI(Manager.java:45)                                                                                                     在   com.example.syeddanish.downloadingimages.Manager.downloadImages(Manager.java:54)                                                                                                     在   com.example.syeddanish.downloadingimages.MainActivity.downloadImages(MainActivity.java:24)                                                                                                     在java.lang.reflect.Method.invoke(本机方法)                                                                                                     在   android.support.v7.app.AppCompatViewInflater $ DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)                                                                                                     在android.view.View.performClick(View.java:6291)                                                                                                     在android.view.View $ PerformClick.run(View.java:24931)                                                                                                     在android.os.Handler.handleCallback(Handler.java:808)                                                                                                     在android.os.Handler.dispatchMessage(Handler.java:101)                                                                                                     在android.os.Looper.loop(Looper.java:166)                                                                                                     在android.app.ActivityThread.main(ActivityThread.java:7425)                                                                                                     在java.lang.reflect.Method.invoke(本机方法)                                                                                                     在   com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:245)                                                                                                     在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

请指出我在做错什么,以及为解决此问题需要进行哪些更改。

2 个答案:

答案 0 :(得分:2)

findViewById是一种根据official documentation的View方法:

  

查找具有给定ID的第一个后代视图;如果ID匹配getId(),则查找本身;如果ID无效(<0)或层次结构中不存在匹配的视图,则查找null。

或一种活动方法:

  

查找由onCreate(Bundle)中处理的android:id XML属性标识的视图

很简单,它可以在父视图中找到一个视图。在大多数情况下,在Activity,Fragment或CustomView内部调用findviewById()。在那里,我们打电话:

this.findViewById(ID_OF_THE_CHILD)

因此,如果要检索 R.id.linearLayoutScrollView ,则需要引用父视图。您可以像这样从 buildGUI 传递它:

public void buildUI(View parent) {
...
linearLayoutScrollView = (LinearLayout)parent.findViewById(R.id.linearLayoutScrollView);
}

因此,例如在“活动”中,您将致电

buildGUI(findViewById(R.layout.activity_main));

答案 1 :(得分:1)

将其放在MainActivity类中解决的问题      linearLayoutScrollView =(LinearLayout)findViewById(R.id.linearLayoutScrollView); 然后将此linearLayoutScrollView作为参数传递给“ Manager”类的构造函数中。

public Manager(Context context, ArrayList<String> urls,LinearLayout linearLayoutScrollView) {
        this.context = context;
        this.urls = urls;
        this.linearLayoutScrollView = linearLayoutScrollView;
    }

,然后将此linearLayoutScrollView设置为“ Manager”类的本地成员,并根据需要使用它。