我正在制作一个图像下载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)
请指出我在做错什么,以及为解决此问题需要进行哪些更改。
答案 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”类的本地成员,并根据需要使用它。