Собственный адаптер и int android.view.View.getImportantForAccessibility()
Пишу собственный адаптер для отображения сообщений (текст,картинка,2 кнопки, текст). Столкнулся с такой проблемой: при отображении собственного ListView. Приложение вылетает с ошибкой:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.sttmmessenger, PID: 7402
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()' on a null object reference
at android.widget.AbsListView.obtainView(AbsListView.java:2508)
at android.widget.ListView.measureHeightOfChildren(ListView.java:1301)
at android.widget.ListView.onMeasure(ListView.java:1203)
at android.view.View.measure(View.java:19147)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:825)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:511)
at android.view.View.measure(View.java:19147)
at android.support.constraint.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
at android.support.constraint.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
at android.view.View.measure(View.java:19147)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6136)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:223)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
at android.view.View.measure(View.java:19147)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6136)
at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:401)
at android.view.View.measure(View.java:19147)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6136)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:223)
at android.view.View.measure(View.java:19147)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6136)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1723)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:788)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:648)
at android.view.View.measure(View.java:19147)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6136)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:223)
at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2693)
at android.view.View.measure(View.java:19147)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2484)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1443)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1697)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1324)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6712)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
at android.view.Choreographer.doCallbacks(Choreographer.java:696)
at android.view.Choreographer.doFrame(Choreographer.java:631)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
В чём причина? Где копать?
Код Адаптера OneMessageAdapter
package com.example.sttmmessenger;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import java.security.SecureRandom;
import android.widget.TextView;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MessageAdapter extends ArrayAdapter<OneMessage> {
ViewHolder viewHolder;
MediaPlayer mediaPlayer;
private static final String CHAR_LOWER = "abcdefghijklmnopqrstuvwxyz";
private static final String CHAR_UPPER = CHAR_LOWER.toUpperCase();
private static final String NUMBER = "0123456789";
private static final String DATA_FOR_RANDOM_STRING = CHAR_LOWER + CHAR_UPPER + NUMBER;
private static SecureRandom random = new SecureRandom();
OneMessage product;
private LayoutInflater inflater;
private int layout;
private ArrayList<OneMessage> productList;
public MessageAdapter(Context context, int resource, List<OneMessage> objects) {
super(context, resource, objects);
this.inflater = inflater;
this.layout = layout;
this.productList = productList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String str=String.valueOf(layout);
if(convertView==null&&inflater!=null&&parent!=null&&str!=null){
convertView = inflater.inflate(R.layout.messagelistview, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}
else{
if(convertView!=null)viewHolder = (ViewHolder) convertView.getTag();
}if(productList!=null&&productList.get(position)!=null) {
product = productList.get(position);
}
if(viewHolder!=null) viewHolder.message_text.setText(product.getText());
if(product!=null) if(product.getPicture()!=null) {
byte[] decodedString = Base64.decode(product.getPicture(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
viewHolder.image.setImageBitmap(decodedByte);
}
if(viewHolder!=null) viewHolder.hear_button.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onClick(View v) {
if(product!=null)
if(product.getVoice()!=null&&product.getVoice_text()!=null){
String path =generateRandomString(10)+".wav";
decoder(product.voice,path);
try {
StartPlayer(path);
} catch (IOException e) {
e.printStackTrace();
}
if(viewHolder!=null) viewHolder.message_transcripted_audio.setText(product.getVoice_text());
}
}
});
if(viewHolder!=null) viewHolder.transcript_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
return convertView;
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static void decoder(String base64Image, String pathFile) {
try (FileOutputStream imageOutFile = new FileOutputStream(pathFile)) {
byte[] imageByteArray = Base64.decode(base64Image,0);
imageOutFile.write(imageByteArray);
} catch (FileNotFoundException e) {
} catch (IOException ioe) {
}
}
public static String generateRandomString(int length) {
if (length < 1) throw new IllegalArgumentException();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
// 0-62 (exclusive), random returns 0-61
if(DATA_FOR_RANDOM_STRING!=null) {
int rndCharAt = random.nextInt(DATA_FOR_RANDOM_STRING.length());
char rndChar = DATA_FOR_RANDOM_STRING.charAt(rndCharAt);
sb.append(rndChar);
}
}
if(sb!=null)
return sb.toString();else return "asdsdasadsadadwasdadwasdawdasdwads";
}
public void StartPlayer(String filePath) throws IOException {
mediaPlayer = new MediaPlayer();
if(mediaPlayer!=null) {
mediaPlayer.setDataSource(filePath);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
Log.d("AUDIOSTATUS", "prepareAsync");
mediaPlayer.setOnPreparedListener((MediaPlayer.OnPreparedListener) this);
mediaPlayer.prepareAsync();
mediaPlayer.start();
}
}
}
class ViewHolder {
Button transcript_button, hear_button;
TextView message_text, message_transcripted_audio;
ImageView image;
ViewHolder(View view){
transcript_button = (Button) view.findViewById(R.id.transcript_audio);
hear_button = (Button) view.findViewById(R.id.playaurdio);
message_text = (TextView) view.findViewById(R.id.text_message);
message_transcripted_audio = (TextView) view.findViewById(R.id.transcripted_text);
image=(ImageView)view.findViewById(R.id.image_from_message);
}
}
Код Класса OneMessage
package com.example.sttmmessenger;
public class OneMessage {
public String picture;
public String text;
public int pos;
public String voice_text;
public String file;
public String voice;
public String filereso;
public OneMessage(String picture, String text, int pos, String voice_text, String file, String voice, String filereso) {
this.picture = picture;
this.text = text;
this.pos = pos;
this.voice_text = voice_text;
this.file = file;
this.voice = voice;
this.filereso = filereso;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getPos() {
return pos;
}
public void setPos(int pos) {
this.pos = pos;
}
public String getVoice_text() {
return voice_text;
}
public void setVoice_text(String voice_text) {
this.voice_text = voice_text;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public String getVoice() {
return voice;
}
public void setVoice(String voice) {
this.voice = voice;
}
public String getFilereso() {
return filereso;
}
public void setFilereso(String filereso) {
this.filereso = filereso;
}
}
Код рабочего класса peripiska.java
package com.example.sttmmessenger;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.google.gson.Gson;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class Perepiska extends AppCompatActivity {
ArrayList<OneMessage> messages_your = new ArrayList();
ArrayList<OneMessage> messages_its = new ArrayList();
class oneMessResponse {
String status;
public OneMessage[] Your;
public OneMessage[] its;
public String toStringerMessage() {
Log.i("MESSAGE_RESPONSE","status:"+status +'\n'+ "yours: " + Your + '\n' + ",its:" + its);
return "MessageResponse{"+"status:"+status +'\n'+ "yours: " + Your + '\n' + ",its:" + its + ')';
}
}
String nick = null;
String sobesednik = null;
void parser( OneMessage[] its) {
int lgth;
lgth = its.length;
String lengt = String.valueOf(lgth);
Log.i("LENGTH_OF_ARRAY:", String.valueOf(lgth));
OneMessage sobmsg[] = new OneMessage[lgth];
Log.i("ЦИКЛ","ЩАС НАЧНЁтся");
for (int i = 0; i <= lgth - 1; i++) {
Log.i("ЦИКЛ","WORKS");
if(i==its[i].pos){
sobmsg[i]=its[i];
messages_its.add(new OneMessage(sobmsg[i].getPicture(),sobmsg[i].getText(),sobmsg[i].getPos(),sobmsg[i].getVoice_text(),sobmsg[i].getFile(),sobmsg[i].getVoice(),sobmsg[i].getFilereso()));
Log.i("MESSAGE:","PICTURE:"+sobmsg[i].getPicture()+",TEXT:"+sobmsg[i].getText()+",POSITION:"+i);
}else{sobmsg[i]=null;
messages_its.add(new OneMessage("","",i,"","","",""));
Log.i("MESSAGE:","ВСЁ КАВЫЧКИ"+i);
Log.d("His MESS",sobmsg[i].text);}
Log.i("FOR","WORKS");
}
// ListView yourm = (ListView) findViewById(R.id.ListViewYou);
ListView itsm = (ListView)findViewById(R.id.ListSobesednik);
// MessageAdapter yoursm = new MessageAdapter(this,R.layout.messagelistview,messages_your);
MessageAdapter itsmad = new MessageAdapter(this,R.layout.messagelistview,messages_its);
// yourm.setAdapter(yoursm);
itsm.setAdapter(itsmad);
Log.i("SETED","SUCCESFULL");
}
class getMessages extends AsyncTask {
Perepiska.oneMessResponse response;
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
if(response!=null) if(response.its!=null)
parser( response.its);else if(response.its==null)Log.d("NETU","EGO SOOBSH"); }
@Override
protected Object doInBackground(Object[] objects) {
String set_server_url = "IP Адрес";//в приложении стоит нормальный
URL url1 = null;
try {
url1 = new URL(set_server_url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
if (url1 != null) {
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) url1.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
urlConnection.setDoOutput(true);
OutputStream out = null;
try {
out = urlConnection.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
char c = '"';
String action = "get_mess";
String gm = "{\"action\":" + c + action + c + "," + "\"nickname\":" + c + nick + c + "," + "\"sobesednik\":" + c + sobesednik + c + "}";
try {
if (out != null) {
out.write(gm.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
Gson gson = new Gson();
response = null;
try {
response = gson.fromJson(new InputStreamReader(urlConnection.getInputStream()), Perepiska.oneMessResponse.class);
if (response != null) {
response.toStringerMessage();
urlConnection.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
if (response != null) {
response.toStringerMessage();
return response;
}
}
return 0;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_perepiska);
Bundle arguments = getIntent().getExtras();
if (arguments != null) {
nick = (String) arguments.get("username");
sobesednik = (String) arguments.get("name_sobesednik");
getMessages gm = new getMessages();
gm.execute();
}
}
}
Разметка элемента собственного ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/message_list_adapter"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_message"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="5"
android:gravity="center"
android:text=""
android:textAlignment="center"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/playaurdio"
android:layout_width="57dp"
android:layout_height="match_parent"
android:text="PLY" />
<Button
android:id="@+id/transcript_audio"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:text="TRS" />
</LinearLayout>
<TextView
android:id="@+id/transcripted_text"
android:layout_width="match_parent"
android:layout_height="81dp" />
<ImageView
android:id="@+id/image_from_message"
android:layout_width="match_parent"
android:layout_height="128dp"
android:layout_weight="25" />
</LinearLayout>
Разметка perepiska_activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Perepiska">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/ListSobesednik"
android:layout_width="202dp"
android:layout_height="match_parent" />
<ListView
android:id="@+id/ListViewYou"
android:layout_width="203dp"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp" />
<LinearLayout
android:id="@+id/layout_bottom_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#00BCD4"
android:gravity="right"
android:orientation="horizontal"
android:padding="5dip">
<EditText
android:id="@+id/message"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_alignTop="@+id/layout_bottom_bar" />
<Button
android:id="@+id/file"
android:text="Ф"
android:layout_width="50dp"
android:layout_height="50dp" />
<Button
android:id="@+id/image"
android:text="И"
android:layout_width="50dp"
android:layout_height="50dp" />
<Button
android:id="@+id/send"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#D36964"
android:text="ОТПР"
android:textColor="#FFFFFF" />
</LinearLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
Ответы (1 шт):
Автор решения: Егор Приставка
→ Ссылка
Преобразовал код адаптера в следующее(оно теперь работает и легко может быть модернизировано)
package com.example.sttmmessenger;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class MessageAdapter extends BaseAdapter {
private LayoutInflater LInflater;
private ArrayList<OneMessage> list;
public MessageAdapter(Context context, ArrayList<OneMessage> data){
list = data;
LInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return list.size();
}
@Override
public OneMessage getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
OneMessage getData(int position){
return (getItem(position));
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if ( v == null){
holder = new ViewHolder();
v = LInflater.inflate(R.layout.messagelistview, parent, false);
holder.hear_button=v.findViewById(R.id.playaurdio);
holder.message_text=v.findViewById(R.id.text_message);
holder.message_transcripted_audio=v.findViewById(R.id.transcripted_text);
holder.transcript_button=v.findViewById(R.id.transcript_audio);
holder.image=v.findViewById(R.id.image_from_message);
v.setTag(holder);
}
holder = (ViewHolder) v.getTag();
OneMessage dataFlags = getData(position);
holder.message_text.setText(dataFlags.getText());
if(dataFlags.getVoice()==null&&dataFlags.getVoice_text()==null){
holder.transcript_button.getLayoutParams().width=0;
holder.transcript_button.getLayoutParams().height=0;
holder.hear_button.getLayoutParams().width=0;
holder.hear_button.getLayoutParams().height=0;
}
if(dataFlags.getPicture()==null){
holder.image.getLayoutParams().width=0;
holder.image.getLayoutParams().height=0;
}
return v;
}
class ViewHolder {
Button transcript_button, hear_button;
TextView message_text, message_transcripted_audio;
ImageView image;
}}